Skip to content

Instantly share code, notes, and snippets.

@magicien
Created October 3, 2017 00:54
Show Gist options
  • Save magicien/4ff6d19968ac07f1eaa4d588ecf8b5c9 to your computer and use it in GitHub Desktop.
Save magicien/4ff6d19968ac07f1eaa4d588ecf8b5c9 to your computer and use it in GitHub Desktop.
How should I inherit Codable class?
import Foundation
let json = """
{
"a": 1,
"b": 2,
"c": 3
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
class A: Codable {
let a: Int
}
let a = try! decoder.decode(A.self, from: json)
dump(a) // a: 1
class B: A {
// let b: Int // 初期値が無いとコンパイルエラーになる
var b: Int = 0
// CodingKeys を指定しても結果は同じ(bが無視される)
}
let b = try! decoder.decode(B.self, from: json)
dump(b) // a: 1, b: 0
class C: A {
var c: Int = 0
// super.init を呼べばaはパースされるが、cは無視される。
required init(from decoder: Decoder) throws {
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
}
}
let c = try! decoder.decode(C.self, from: json)
dump(c) // a: 1, c: 0
class B2: A {
let b: Int
enum CodingKeys: String, CodingKey {
case b
}
// 自分で真面目にパースすれば大丈夫。
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.b = try container.decode(Int.self, forKey: .b)
try super.init(from: decoder)
}
}
let b2 = try! decoder.decode(B2.self, from: json)
dump(b2) // a: 1, b: 2
class C2: B {
let c: Int
enum CodingKeys: String, CodingKey {
case c
}
// initを書いていないBは素通りするけど、aとcはパースできる。
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.c = try container.decode(Int.self, forKey: .c)
try super.init(from: decoder)
}
}
let c2 = try! decoder.decode(C2.self, from: json)
dump(c2) // a: 1, b: 0, c: 3
class C3: B2 {
let c: Int
// CodingKeys はB2で使っているので同じ名前を使うと怒られる
//enum CodingKeys: String, CodingKey {
enum MyCodingKeys: String, CodingKey {
case c
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: MyCodingKeys.self)
self.c = try container.decode(Int.self, forKey: .c)
try super.init(from: decoder)
}
}
let c3 = try! decoder.decode(C3.self, from: json)
dump(c3) // a: 1, b: 2, c: 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment