I've been struggling with this for a while. I have a JSON that I get from an API call, but it has a key which can either be false ou return a value if it's true.
like this:
{
"id": 550,
"favorite": true,
"rated": {
"value": 8
},
"watchlist": false
}
or this:
{
"id": 550,
"favorite": true,
"rated": false,
"watchlist": false
}
I tried to decode it like this:
struct AccountState: Decodable {
var id: Int?
var favorite: Bool?
var rated: CustomValue
var watchlist: Bool?
}
struct RatingValue: Decodable {
var value: Double?
}
enum CustomValue: Decodable {
case bool(Bool)
case rating(RatingValue)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let bool = try? container.decode(Bool.self) {
self = .bool(bool)
} else if let rating = try? container.decode(RatingValue.self) {
self = .rating(rating)
} else {
let context = DecodingError.Context(codingPath: container.codingPath, debugDescription: "Unknown type")
throw DecodingError.dataCorrupted(context)
}
}
}
in ViewController:
func dowloadAndDecodeData() {
let url...
...
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
guard let accountState = try? decoder.decode(AccountState.self, from: data) else {
print("error")
return
}
print(accountState)
}
In the console I can see the JSON content is correctly parsed (returning either false or value if it exists).
The question is: how can I access this value from code? Since "rated" is of type "CustomValue", I can't just do accountState.rated.value
like I would normally use.