Swift Codable Decode Manually Optional Variable
Solution 1
Age is optional:
let age: String?
So try to decode in this way:
let age: String? = try values.decodeIfPresent(String.self, forKey: .age)
Solution 2
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.
Charlie Fish
Software Engineer (iOS @ ForeFlight) 🖥📱, student pilot ✈️, HUGE Colorado Avalanche fan 🥅, entrepreneur (rrainn, Inc.) ⭐️ Contact me ✉️, About me 👨🏻💻, Terms 📝, Website 🌐
Updated on June 03, 2022Comments
-
Charlie Fish about 2 years
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 thatinit
function out it works fine. The error isNo 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.