Codable协议是在Swift中引入的,目的是简化数据序列化和反序列化的过程,例如JSON或属性列表。之前需要手动实现解析,这既繁琐又容易出错,且可读性差。自动化该过程使得开发更安全,更简洁的代码成为可能。
问题在于,当自动应用Codable时,所有属性也必须是Codable,任何此链条的破坏都需要显式实现解码和编码方法。此外,处理结构、带有继承的类以及自定义键映射时还需要注意一些特性。
解决方案是将Codable用于简单模型,严格监控哪些属性应该序列化,对于复杂模型实现encode(to:)和init(from:)方法,并使用CodingKeys进行键映射。
代码示例:
struct User: Codable { let id: Int let name: String let email: String? enum CodingKeys: String, CodingKey { case id case name = "full_name" case email = "contact_email" } }
关键特性:
带有继承和独特子属性的类是否可以自动通过Codable正确序列化?
不可以,对于带有继承的类,Swift要求在子类中手动实现encode(to:)和init(from:),否则父类和子类的属性将无法正确序列化。示例:
class Animal: Codable { let species: String } class Dog: Animal { let breed: String enum CodingKeys: String, CodingKey { case breed } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) breed = try container.decode(String.self, forKey: .breed) try super.init(from: decoder) } override func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(breed, forKey: .breed) try super.encode(to: encoder) } }
如果结构中的属性被标记为private,而使用自动Codable会发生什么?
如果属性是private且没有明确声明为var/let伴随CodingKeys,它将无法序列化或反序列化。因此,对于private属性,必须声明CodingKeys,并在需要时将其包含在枚举中。
是否可以仅为解码(只读)实现Codable?
可以,只需实现init(from:)并将类型遵循Decodable协议而非Codable即可。
struct ReadOnlyModel: Decodable { let id: Int }
负面案例
开发者在模型中添加了计算属性,但没有实现自定义的encode和decode方法,期望Codable自动处理。
优点:
缺点:
积极案例
开发者实现了自定义的CodingKeys和自定义的encode/decode方法,处理复杂情况,其中属性与键不匹配,具有计算字段,并应用继承。
优点:
缺点: