I have an API JSON response like below. I want to decode the JSON to get an array of dictionary [String:Double]
, like [{"2020-01-01" : 0.891186}, {"2020-01-02" : 0.891186}]
.
{
"rates": {
"2020-01-01": {
"EUR": 0.891186
},
"2020-01-02": {
"EUR": 0.891186
},
"2020-01-03": {
"EUR": 0.895175
},
"2020-01-04": {
"EUR": 0.895175
}
}
}
I have written decode code like below:
do {
let data = try Data(contentsOf: appURL)
let decoder = JSONDecoder()
let response = try decoder.decode(Rates.self, from: data)
response.rates
} catch let jsonError {
print(jsonError)
}
And I have tried to define a struct:
struct Rates: Codable, Hashable {
let rates: Point
}
struct Point {
}
But I don't have an idea about what I should write in struct Point
because the date is not a consistent field.
CodePudding user response:
struct Rates: Codable {
let rates: [String: Point]
}
// MARK: - Point
struct Point: Codable {
let eur: Double
enum CodingKeys: String, CodingKey {
case eur = "EUR"
}
}
you can do something like this
CodePudding user response:
Here are two possible solutions, one with the struct Point
and the other one with a dictionary instead
First the solution with Point
struct Point: Codable {
let date: String
let rate: Double
}
And then create a custom init(from:)
where we decode the json into a dictionary first, [String: [String: Double]]
and then map that dictionary into an array of Point
struct Rates: Codable {
let rates: [Point]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let dictionary = try container.decode([String: [String: Double]].self, forKey: .rates)
rates = dictionary.map { Point(date: $0.key, rate: $0.value.first?.value ?? .zero) }
}
}
And here is the second solution using a dictionary
struct Rates: Codable {
let rates: [String: Double]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let dictionary = try container.decode([String: [String: Double]].self, forKey: .rates)
rates = dictionary.compactMapValues { $0.first?.value }
}
}