Nick Kohrn
Nick Kohrn

Reputation: 6039

Using Swift 4 Codable Protocol with Unknown Dictionary Keys

I am working with NASA's Near Earth Object Web Service to retrieve data to be displayed in an application. I understand how to use Swift 4's Codable protocol, but I do not understand how to map part of the response.

Using Paw, I inspected the response from the API:

Image of API response data

As you can see, the near_earth_objects structure is a Dictionary, and the keys are dates. The issue is that the URL parameters are dates, so these date structures will change, depending on the day of the request. Therefore, I do not know how I can create properties to be automatically mapped when using the Codable protocol.

The data that I am trying to get to inside of these structures are Arrays that contain Dictionarys:

Image of API response data

How can I have my model object conform to the Codable protocol and map these structures when the dates will change as the dates of the requests change?

Upvotes: 1

Views: 1715

Answers (2)

David Pasztor
David Pasztor

Reputation: 54706

You don't need to know the keys of the Dictionary compile time if you don't mind keeping a Dictionary after decoding.

You just need to specify the property with type Dictionary<String:YourCustomDecodableType>. The keys will be dates corresponding to observation and the value will an array of all objects with your custom type.

struct NearEarthObject: Codable {
    let referenceID:String
    let name:String
    let imageURL:URL

    private enum CodingKeys: String, CodingKey {
        case referenceID = "neo_reference_id"
        case name
        case imageURL = "nasa_jpl_url"
    }
}

struct NEOApiResponse: Codable {
    let nearEarthObjects: [String:[NearEarthObject]]

    private enum CodingKeys: String,CodingKey {
        case nearEarthObjects = "near_earth_objects"
    }
}

do {
    let decodedResponse = try JSONDecoder().decode(NEOApiResponse.self, from: data)
} catch {
    print(error)
}

Upvotes: 2

LowKostKustomz
LowKostKustomz

Reputation: 424

As you said, near_earth_objects is a Dictionary, but keys are not Dates, keys are Strings, and values are arrays of the known structures. So the above code will work:

...
let nearEarthObjects: [String: [IndexObject]]
...

enum CodingKey: String, CodingKeys {
    case nearEarthObjects = "near_earth_objects"
}

struct IndexObject: Decodable {
    ...
    let name: String
    ...
}

Upvotes: 0

Related Questions