My client has a service that returns Article objects. There is an id property that it is of type UInt64. In the same api when you ask for category articles you get a response with articles but the id is a String. There is no way at the moment that someone will change this stupid thing so I have to find a workaround to parse both answers. My model is something like this:
struct Article {
let id: UInt64
let categoryName: String?
}
extension Article: Decodable {
private enum Keys: String, CodingKey {
case id
case categoryName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Keys.self)
id = try container.decode(UInt64.self, forKey: Keys.id)
categoryName = try container.decodeIfPresent(String.self, forKey: Keys.categoryName)
}
How to check the type of Keys.id and use the correct method to decode? I have to use both
id = try container.decode(UInt64.self, forKey: Keys.id)
id = try container.decode(String.self, forKey: Keys.id)
to parse my objects correctly in both cases. Thanks in advance
If you want workaround, then below answer does that. I don't know if this is also a possible good way to do this. Looking forward to improve this answer. Suggestions are welcome.
extension Article: Decodable {
private enum Keys: String, CodingKey {
case id
case categoryName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Keys.self)
// check if id is of type UInt64
do{
id = try container.decodeIfPresent(UInt64.self, forKey: Keys.id) ?? 0
}catch{
// if id is of String type convert it to UInt64
// do catch can be used here too
let str = try container.decodeIfPresent(String.self, forKey: Keys.id)
id = UInt64(str ?? "0") ?? 0
}
categoryName = try container.decode(String.self, forKey: Keys.categoryName)
}
}