Codable 是 Swift 中的一个协议,它是 Encodable 和 Decodable 协议的组合,用于在对象与外部数据格式(如 JSON、Plist 或其他自定义格式)之间进行编码和解码。这个协议使得对象可以轻松地进行序列化和反序列化操作。
• Encodable:表示可以将对象编码成外部格式(例如 JSON)。
• Decodable:表示可以从外部格式解码为对象。
Codable 是这两个协议的合成,表示可以同时编码和解码。
- 为什么需要 Codable?
通常我们需要将数据从应用的内存模型转换为可以存储或传输的格式(如 JSON),然后从存储或接收到的数据中恢复对象。Codable 协议提供了这种序列化和反序列化的能力,使得开发者能够方便地与外部数据交互。
- 如何使用 Codable
- 定义一个符合 Codable 协议的类或结构体
你只需要在结构体或类声明中声明符合 Codable 协议即可。如果对象的属性本身也符合 Codable 协议,Swift 会自动推断出整个结构体或类也符合 Codable。
import Foundation
struct Person: Codable {
var name: String
var age: Int
var isEmployed: Bool
}
上面定义的 Person 结构体符合 Codable 协议,因为它的所有属性 (name, age, isEmployed) 都是 Codable 类型(String, Int, Bool)。
- 编码为 JSON(encode)
你可以使用 JSONEncoder 来将 Codable 对象编码为 JSON 数据。
let person = Person(name: "John Doe", age: 30, isEmployed: true)
do {
let encoder = JSONEncoder()
let data = try encoder.encode(person)
// 将 Data 转换为字符串(可选)
if let jsonString = String(data: data, encoding: .utf8) {
print(jsonString)
}
} catch {
print("编码失败: \(error)")
}
在这个例子中,我们将 person 对象编码为 JSON 数据。编码成功后,我们可以将 data 转换为字符串形式来查看其内容。
- 解码 JSON 为对象(decode)
你也可以使用 JSONDecoder 将 JSON 数据解码为 Codable 对象。
let jsonData = """
{
"name": "John Doe",
"age": 30,
"isEmployed": true
}
""".data(using: .utf8)!
do {
let decoder = JSONDecoder()
let decodedPerson = try decoder.decode(Person.self, from: jsonData)
print(decodedPerson)
} catch {
print("解码失败: \(error)")
}
在这个例子中,我们有一段 JSON 数据,使用 JSONDecoder 将其解码成 Person 类型的对象。解码后,我们可以访问 decodedPerson 对象的属性。
- 自定义编码和解码
你可以通过实现 encode(to:) 和 init(from:) 方法来自定义对象的编码和解码过程,尤其是在你的对象结构与外部数据格式不完全匹配时。
struct Person: Codable {
var name: String
var age: Int
enum CodingKeys: String, CodingKey {
case name
case age = "yearsOld" // "yearsOld" 在 JSON 中而不是 "age"
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
// 自定义解码
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.age = try container.decode(Int.self, forKey: .age)
}
// 自定义编码
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(age, forKey: .age)
}
}
在这个例子中,我们自定义了 CodingKeys 枚举来指定 age 在 JSON 中的键是 yearsOld,而在模型中还是 age。通过实现 init(from:) 和 encode(to:) 方法,我们可以精细控制如何解码和编码对象。
- 常见的 Codable 错误
• 属性类型不符合 Codable 协议:如果你的结构体或类的某个属性类型不符合 Codable 协议(例如自定义类型没有实现 Codable),则会导致编码或解码失败。
• 缺少必需的字段:解码时,如果 JSON 数据缺少必需的字段,并且没有为其提供默认值,解码操作将失败。
• 类型不匹配:例如,如果 JSON 数据的某个字段是一个字符串,但模型中该字段是一个整数,解码将会