Codableプロトコルは、JSONやプロパティリストなどのデータのシリアライズとデシリアライズを簡素化するためにSwiftに導入されました。以前は、この処理を手動で実装する必要があり、手間がかかり、エラーが発生しやすく、可読性も低下していました。このプロセスの自動化により、安全で簡潔なコードを開発できるようになりました。
問題点 自動的に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で、明示的にCodingKeysとして宣言されていない場合、それはシリアライズまたはデシリアライズされません。したがって、privateプロパティについては、必ずCodingKeysを宣言し、必要に応じて列挙に含める必要があります。
デコード専用(読み取り専用)でCodableを実装することは可能ですか?
はい、そのためにはinit(from:)を実装し、タイプをCodableではなくDecodableプロトコルに従わせるだけで済みます。
struct ReadOnlyModel: Decodable { let id: Int }
ネガティブケース
開発者は、モデルに計算プロパティを追加し、Codableの自動処理を期待してカスタムメソッドencodeとdecodeを実装しませんでした。
利点:
欠点:
ポジティブケース
開発者は、プロパティがキーと一致しない場合や計算フィールドがある場合、そして継承が適用される場合に、カスタムなCodingKeysとカスタムなencode/decodeメソッドを実装します。
利点:
欠点: