问题
I am unable to set the b
property in a child class. It is the parent class that inherits from Codable
, and that seems to be working well.
I feel like I am missing something really obvious, but I am having trouble seeing the wood for the trees.
Below is a playground example of my problem. b
remains 0, despite being set to 10
. It is the child class that gets passed in, but the parent property that can be set (very weird!).
class Primary : Codable {
var a: Int = 0
}
class Secondary : Primary {
var b: Int = 0
}
let c = Secondary.self
func testRef<T: Codable>(_ t: T.Type) {
let json = "{\"a\":5, \"b\" : 10}".data(using: .ascii)!
let testCodable = try? JSONDecoder().decode(t.self, from: json)
print("a >> \((testCodable as! Primary).a)")
print("b >> \((testCodable as! Secondary).b)")
}
testRef(c)
The output from this is:
a >> 5
b >> 0
Any tips or pointers would be gratefully received.
- tried in Xcode 9.3, Swift 4.1
回答1:
The magic of Codable
relies on simplicity (using structs which don't support inheritance).
The more custom, the more code
You have to write a custom initializer in the subclass to consider inheritance (thanks to Hamish for the note that CodingKeys and initializer are synthesized in the base class), I omitted the Encodable
part intentionally
class Primary : Decodable {
var a: Int
/*
private enum CodingKeys: String, CodingKey { case a }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
a = try container.decode(Int.self, forKey: .a)
}
*/
}
class Secondary : Primary {
var b: Int
private enum CodingKeys: String, CodingKey { case b }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
b = try container.decode(Int.self, forKey: .b)
try super.init(from: decoder)
}
}
func testRef<T: Decodable>() throws -> T {
let json = "{\"a\":5, \"b\" : 10}".data(using: .utf8)!
return try JSONDecoder().decode(T.self, from: json)
}
do {
let secondary : Secondary = try testRef()
print(secondary.a, secondary.b) // 5 10
} catch { print(error) }
来源:https://stackoverflow.com/questions/50091036/using-codable-to-set-property-values-doesnt-work-through-inheritance