Het Codable-protocol werd geïntroduceerd in Swift om het proces van serialisatie en deserialisatie van gegevens, zoals JSON of Property List, te vereenvoudigen. Eerder moest dit handmatig worden geïmplementeerd, wat tijdrovend, foutgevoelig en moeilijk leesbaar was. De automatisering van dit proces maakte het mogelijk om veiligere en compactere code te ontwikkelen.
Probleem is dat bij automatische toepassing van Codable alle eigenschappen ook Codable moeten zijn, en elke schending van deze keten vereist een expliciete implementatie van de decodering en codering methoden. Daarnaast zijn er bijzonderheden bij het werken met structuren, klassen met overerving, en bij aangepaste key mapping.
Oplossing is om Codable te gebruiken voor eenvoudige modellen, strikt bij te houden welke eigenschappen moeten worden geserialiseerd, en voor complexe modellen de methoden encode(to:) en init(from:) te implementeren, evenals CodingKeys te gebruiken voor key mapping.
Voorbeeldcode:
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" } }
Belangrijke kenmerken:
Kan een klasse met overerving en unieke eigenschappen van de afgeleide klasse automatisch correct worden geserialiseerd met behulp van Codable?
Nee, voor klassen met overerving vereist Swift handmatige implementatie van encode(to:) en init(from:) in subklassen, anders worden de eigenschappen van de ouder en de afstammeling niet correct geserialiseerd. Voorbeeld:
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) } }
Wat gebeurt er als een eigenschap in een structuur als private is gemarkeerd, terwijl automatische Codable wordt gebruikt?
Als de eigenschap private is en niet wordt gedeclareerd als var/let met expliciete CodingKeys, zal deze niet worden geserialiseerd of gedeserialiseerd. Daarom moeten private eigenschappen altijd CodingKeys declareren en, indien nodig, in de enumeratie worden opgenomen.
Is het mogelijk om Codable alleen voor decoding (alleen lezen) te implementeren?
Ja, daarvoor is het genoeg om alleen init(from:) te implementeren en het type aan te passen aan het Decodable-protocol in plaats van Codable.
struct ReadOnlyModel: Decodable { let id: Int }
** Negatieve casus
Een ontwikkelaar voegde een berekend eigenschap toe aan een model, zonder de aangepaste encode en decode methoden te implementeren, hopend op automatische afhandeling van Codable.
Voordelen:
Nadelen:
** Positieve casus
Een ontwikkelaar implementeert aangepaste CodingKeys en aangepaste encode/decode methoden voor complexe gevallen, waar eigenschappen niet overeenkomen met keys, er berekende velden zijn, en overerving wordt toegepast.
Voordelen:
Nadelen: