Swift(iOS/macOS)中的对象序列化:Codable、JSON 和 PropertyList

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

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

推荐