I have the following code:
import Foundation
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": "28"},
{"firstname": "Bob", "lastname": "Smith"}
]
""".data(using: .utf8)!
struct Person: Codable {
let firstName, lastName: String
let age: String?
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
firstName = try values.decode(String.self, forKey: .firstName)
lastName = try values.decode(String.self, forKey: .lastName)
age = try values.decode(String.self, forKey: .age)
}
}
let decoded = try JSONDecoder().decode([Person].self, from: jsonData)
print(decoded)
Problem is it's crashing on age = try values.decode(String.self, forKey: .age)
. When I take that init
function out it works fine. The error is No value associated with key age (\"age\").
.
Any ideas on how to make that optional and not have it crash when it doesn't exist? I also need that init
function for other reasons, but just made a simple example to explain what is going on.
Age is optional:
let age: String?
So try to decode in this way:
let age: String? = try values.decodeIfPresent(String.self, forKey: .age)
In my model, what I did is
var title: String?
...
title = try container.decode(String?.self, forKey: .age)
rather than
name = try? container.decode(String.self, forKey: .age)
For example for some reason backend passes a numeric value for that key, like title: 74
. With the 1st method, you will get error message like this (I wrote a unit test for my model), and you can pinpoint the problem quickly
However, With the 2nd method try?
, this useful error message will be silenced and will not bubble up. You will still get a valid decoding result title = nil
, which actually is not true in most cases, if only null
from backend is supposed to yield a nil
.
But of course, if you design is that no matter what is retrieved from backend, as long as the type does not match, it will be a nil
. Then I think there shouldn't be any problem with the 1st method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With