I have a named array of json objects which I receive via an API call.
{
"Images": [{
"Width": 800,
"Height": 590,
"Url": "https://obfuscated.image.url/image1.jpg"
}, {
"Width": 800,
"Height": 533,
"Url": "https://obfuscated.image.url/image2.jpg"
}, {
"Width": 800,
"Height": 478,
"Url": "https://obfuscated.image.url/image3.jpg"
}]
}
The objects are of type Image, which I have defined and have a decode function which can decode a single Image object. Image looks like:
struct Image : Codable {
let width: CGFloat
let height: CGFloat
let url: String
enum ImageKey: String, CodingKey {
case width = "Width"
case height = "Height"
case url = "Url"
}
init(from decoder: Decoder) throws
{
let container = try decoder.container(keyedBy: ImageKey.self)
width = try container.decodeIfPresent(CGFloat.self, forKey: .width) ?? 0.0
height = try container.decodeIfPresent(CGFloat.self, forKey: .height) ?? 0.0
url = try container.decodeIfPresent(String.self, forKey: .url) ?? ""
}
func encode(to encoder: Encoder) throws
{
}
}
I have a written a test for this scenario but this is where I am stumped! The test fails (naturally) and looks like this:
func testManyImages() throws {
if let urlManyImages = urlManyImages {
self.data = try? Data(contentsOf: urlManyImages)
}
let jsonDecoder = JSONDecoder()
if let data = self.data {
if let _images:[Image] = try? jsonDecoder.decode([Image].self, from: data) {
self.images = _images
}
}
XCTAssertNotNil(self.images)
}
My question is this:
How do I access the array of Images via the name "Images" or otherwise?
Thanks for reading and as always any help always appreciated.
I think your Codable structure is wrong. It should be :
struct JSONStructure: Codable {
let images: [Images]
private enum CodingKeys: String, CodingKey {
case images = "Images"
}
}
struct Images: Codable {
let width: CGFloat
let height: CGFloat
let url: String
private enum CodingKeys: String, CodingKey {
case width = "Width"
case height = "Height"
case url = "Url"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
width = try container.decodeIfPresent(CGFloat.self, forKey: .width) ?? 0.0
height = try container.decodeIfPresent(CGFloat.self, forKey: .height) ?? 0.0
url = try container.decodeIfPresent(String.self, forKey: .url) ?? ""
}
func encode(to encoder: Encoder) throws {
}
}
And then :
if let data = self.data {
if let decoded = try? jsonDecoder.decode(JSONStructure.self, from: data) {
print("Decoded : \(decoded)")
self.images = decoded.images
}
}
Logs :
Decoded : JSONStructure(images: [DreamSiteradio.Images(width: 800.0, height: 590.0, url: "https://obfuscated.image.url/image1.jpg"), DreamSiteradio.Images(width: 800.0, height: 533.0, url: "https://obfuscated.image.url/image2.jpg"), DreamSiteradio.Images(width: 800.0, height: 478.0, url: "https://obfuscated.image.url/image3.jpg")])