Swift Codable Decode Manually Optional Variable

Charlie Fish picture Charlie Fish · Oct 13, 2017 · Viewed 13.2k times · Source

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.

Answer

Oleg Gordiichuk picture Oleg Gordiichuk · Oct 13, 2017

Age is optional:

let age: String? 

So try to decode in this way:

let age: String? = try values.decodeIfPresent(String.self, forKey: .age)