The Codable protocol was introduced in Swift to simplify the process of serialization and deserialization of data such as JSON or Property List. Previously, manual parsing was required, which was labor-intensive, error-prone, and hard to read. Automating this process has allowed for safer and more concise code.
The problem is that when using Codable automatically, all properties must also be Codable, and any violation of this chain requires explicit implementation of decoding and encoding methods. Additionally, there are peculiarities when working with structures, classes with inheritance, and when custom key mapping is involved.
The solution is to use Codable for simple models, strictly monitor which properties should be serialized, and in the case of complex models, implement the methods encode(to:) and init(from:), as well as use CodingKeys for key mapping.
Example code:
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" } }
Key features:
Can a class with inheritance and unique properties of a descendant be automatically serialized using Codable?
No, for classes with inheritance, Swift requires manual implementation of encode(to:) and init(from:) in subclasses; otherwise, the properties of the parent and descendant are not serialized correctly. Example:
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) } }
What happens if a property in a struct is marked as private while using automatic Codable?
If a property is private and not declared as var/let with explicit CodingKeys, it will not be serialized or deserialized. Therefore, for private properties, it is essential to declare CodingKeys and include them in the enumeration when necessary.
Is it possible to implement Codable solely for decoding (read-only)?
Yes, to do this, it is sufficient to implement only init(from:) and conform the type to the Decodable protocol instead of Codable.
struct ReadOnlyModel: Decodable { let id: Int }
Negative case
A developer added a computed property to the model without implementing custom encode and decode methods, hoping for automatic handling by Codable.
Pros:
Cons:
Positive case
A developer implements custom CodingKeys and custom encode/decode methods for complex cases where properties do not match keys, there are computed fields, and inheritance is involved.
Pros:
Cons: