IMGUR image search returns json:
{"data": [{
"title": "Family :)",
"images": [{
"title": null,
"description": null,
"nsfw": null,
"link": "https:\/\/i.imgur.com\/oe5BrCu.jpg",
}]
} ]
}
Model Object is configured:
struct ImgurResponse: Codable {
let data: [ImageData]
}
struct ImageData: Codable {
let title: String
let images: [Image]
}
struct Image: Codable {
let title, description, nsfw: String
let link: String
enum CodingKeys: String, CodingKey {
case title
case description
case nsfw
case link
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
description = try container.decodeIfPresent(String.self, forKey: .description) ?? ""
nsfw = try container.decodeIfPresent(String.self, forKey: .nsfw) ?? ""
link = try container.decodeIfPresent(String.self, forKey: .link) ?? ""
}
Calling JSONDecoder():
let response = try JSONDecoder().decode(ImgurResponse.self, from: data)
When putting a brake point on the last line 'link = ' I land on it about 48 times. As i understand, we are able to create Image object 48 times.
Yet, im getting an error and 'response' isn't created:
Key 'CodingKeys(stringValue: "images", intValue: nil)' not found: No value associated with key CodingKeys(stringValue: "images", intValue: nil) ("images").
codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 49", intValue: 49)]
What other 'safe' decoding practices should I implement?
The error means that one of the JSON objects that you map to ImageData
is missing a key "images"
, yet ImageData
expects it to be there, since it's not optional.
To fix, you need to make the property images
optional:
struct ImageData: Codable {
let title: String
let images: [Image]? // <- here
}
Typically, an optional array is hard to work with, so you might want to consider creating an empty array when the key is missing:
struct ImageData {
let title: String
let images: [Image]
}
extension ImageData: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
images = try container.decodeIfPresent([Image].self, forKey: .images) ?? []
}
}