Swift(iOS/macOS)中的对象序列化:Codable、JSON 和 PropertyList
序列化是将数据对象转换为适合存储或传输的格式(例如 JSON、XML、Property List)的过程。在 Apple 生态系统(iOS、macOS、watchOS、tvOS)中,Swift 提供了一种强大而优雅的序列化和反序列化机制——Codable 协议。在本文中,我们将详细讲解如何使用 Codable、JSONEncoder、PropertyListEncoder 及其类似功能来处理数据。
什么是 Codable?
Codable 是一个组合协议,它结合了 Encodable(用于将对象编码为外部格式)和 Decodable(用于从外部格式解码为对象)。如果您的 Swift 结构体或类遵循 Codable,您将自动获得序列化和反序列化的能力。
基本声明:
struct User: Codable { let id: Int let name: String let email: String}所有标准 Swift 类型(String、Int、Double、Bool、Date、Data、URL,甚至可选类型和数组/字典)都已经遵循 Codable。
编码为 JSON
要将对象编码为 JSON,请使用 JSONEncoder。示例:
let user = User(id: 1, name: "伊万·彼得罗夫", email: "ivan@example.com")let encoder = JSONEncoder()encoder.outputFormatting = .prettyPrinted // 用于美化输出
do { let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("编码错误:\\(error)")}结果:
{ "id" : 1, "name" : "伊万·彼得罗夫", "email" : "ivan@example.com"}从 JSON 解码
要进行反向转换,请使用 JSONDecoder:
let jsonString = """{ "id": 2, "name": "玛丽亚·西多罗娃", "email": "maria@example.com"}"""let jsonData = Data(jsonString.utf8)let decoder = JSONDecoder()
do { let decodedUser = try decoder.decode(User.self, from: jsonData) print("已解码用户:\\(decodedUser.name)")} catch { print("解码错误:\\(error)")}使用 Property List (plist)
要序列化为 XML Property List 格式,请使用 PropertyListEncoder 和 PropertyListDecoder。这对于在配置文件或 UserDefaults 中存储数据非常有用。
// 编码为 plistlet encoder = PropertyListEncoder()encoder.outputFormat = .xml
do { let plistData = try encoder.encode(user) // plistData 可以保存到文件或 UserDefaults 中} catch { print("plist 编码错误:\\(error)")}
// 从 plist 解码let decoder = PropertyListDecoder()do { let decodedUser = try decoder.decode(User.self, from: plistData) print(decodedUser)} catch { print("plist 解码错误:\\(error)")}自定义键 (CodingKeys)
有时 Swift 中的属性名称与 JSON 中的键不匹配。为此,可以使用 CodingKeys 枚举:
struct Product: Codable { let productId: Int let productName: String let price: Double
enum CodingKeys: String, CodingKey { case productId = "product_id" case productName = "product_name" case price }}现在,带有键 product_id 和 product_name 的 JSON 将被正确处理。
处理日期和其他特殊类型
默认情况下,JSONEncoder 和 JSONDecoder 将日期编码为 TimeInterval