I have a base model called Requirements
and another more specific model called AccountRequirements
.
When I try to read the currentDeadline
property, if i use Requirements
it works fine. If I use AccountRequirements
it comes out as nil
.
I do not understand why. I'm guessing it has to do somehow with the class
. I always use struct
in my models but since I can not inherit from a struct
I'm using class
here.
class Requirements: Codable {
var commonProperty: String
// works
var currentDeadline: Int?
enum CodingKeys: String, CodingKey {
case commonProperty = "common_property"
case currentDeadline = "current_deadline"
}
}
class AccountRequirements: Requirements {
// doesnt work
var currentDeadline: Int?
enum CodingKeys: String, CodingKey {
case currentDeadline = "current_deadline"
}
}
I decode data like this:
documentReference.addSnapshotListener { [self] documentSnapshot, error in
guard let document = documentSnapshot else {
self.error = error!.localizedDescription
return
}
self.user = try? document.data(as: Requirements.self)
}
If you want to decode it as the subclass then you need to give that class and not the superclass to document.data(as:)
. You also need to implement init(from:)
for the subclass to decode it properly
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
currentDeadline = try container.decodeIfPresent(Int.self, forKey: .currentDeadline)
try super.init(from: decoder)
}
Below is an example with a hardcoded json value
let data = """
{ "common_property": "Some text",
"current_deadline": 42
}
""".data(using: .utf8)!
do {
let result = try JSONDecoder().decode(Requirements.self, from: data)
print(type(of: result), result.commonProperty)
let result2 = try JSONDecoder().decode(AccountRequirements.self, from: data)
print(type(of: result2), result2.commonProperty, result2.currentDeadline ?? "")
} catch {
print(error)
}
Requirements Some text
AccountRequirements Some text 42