为了获得更大的灵活性和健壮性,您可以实施Age
枚举以完全支持您的数据模型;)例如:
enum Age: Decodable {
case realAge(String)
case fakeAge(String)
private enum CodingKeys: String, CodingKey {
case realAge = "realage", fakeAge = "fakeage"
}
init(from decoder: Decoder) throws {
let dict = try decoder.container(keyedBy: CodingKeys.self)
if let age = try dict.decodeIfPresent(String.self, forKey: .realAge) {
self = .realAge(age)
return
}
if let age = try dict.decodeIfPresent(String.self, forKey: .fakeAge) {
self = .fakeAge(age)
return
}
let errorContext = DecodingError.Context(
codingPath: dict.codingPath,
debugDescription: "Age decoding failed"
)
throw DecodingError.keyNotFound(CodingKeys.realAge, errorContext)
}
}
然后在您的Person
类型中使用它:
struct Person: Decodable {
let firstName, lastName: String
let age: Age
enum CodingKeys: String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
var realAge: String? {
switch age {
case .realAge(let age): return age
case .fakeAge: return nil
}
}
}
像以前一样解码:
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": {"realage": "28"}},
{"firstname": "Bob", "lastname": "Smith", "age": {"fakeage": "31"}}
]
""".data(using: .utf8)!
let decoded = try! JSONDecoder().decode([Person].self, from: jsonData)
for person in decoded { print(person) }
印刷:
人(名字:“汤姆”,姓氏:“史密斯”,年龄:Age.realAge(“28”))
人(名字:“鲍勃”,姓氏:“史密斯”,年龄:Age.fakeAge(“31”))
最后,新的realAge
计算属性提供了您最初所追求的行为(即,非零仅适用于实际年龄):
for person in decoded { print(person.firstName, person.realAge) }
汤姆可选(“28”)
鲍勃无