Mirella Candy
Mirella Candy

Reputation: 77

Swift Codable: Decoding dynamic keys

I'm trying to practice Swift's Codable API. I send a network request and I receive one single line each time as follows where I have to deal with dynamic keys :

Response example 1:

{
  "EUR": 4695.01
}

Response example 2:

{
  "USD": 479.01
}

Response example 3:

{
  "BTC": 4735.01
}

I tried this method to parse the dynamic keys :

struct ConversionResponseModel: Decodable {
    typealias destinationCurrency = String
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
    }
}

and my fetching request :

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

But I get this as a result : ConversionResponseModel(), but not the currency values. It sounds like I'm missing something. Any help please. Thank you

Upvotes: 1

Views: 2492

Answers (1)

jnpdx
jnpdx

Reputation: 52625

You're almost there. The JSON you're getting will return a dictionary of [String:Double]. You can then covert that using:

struct ConversionResponseModel: Decodable {
    typealias DestinationCurrency = String
    
    let currency : DestinationCurrency
    let value : Double
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let dict = try container.decode([String:Double].self)
        guard let key = dict.keys.first else {
            throw NSError(domain: "Decoder", code: 0, userInfo: [:])
        }
        currency = key
        value = dict[key] ?? -1
    }
}

Note: taking into account Rob Napier's comment, you could substitute Decimal for Double -- see his comment on the original question for more detail

Upvotes: 3

Related Questions