I am trying to call an API and I am trying to map the response to a model class. But each time, I am getting a an error that invalid data.
Api call is as follows.
let endpoint = "http://apilayer.net/api/live?access_key=baab1114aeac6b4be74138cc3e6abe79¤cies=EUR,GBP,CAD,PLN,INR&source=USD&format=1"
guard let url = URL(string: endpoint) else {
completed(.failure(.invalidEndPoint))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let _ = error {
completed(.failure(.unableToComplete))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let convertedValues = try decoder.decode([Converted].self, from: data)
completed(.success(convertedValues))
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
}
Sample Response is as follows.
{
"success":true,
"terms":"https:\/\/currencylayer.com\/terms",
"privacy":"https:\/\/currencylayer.com\/privacy",
"timestamp":1610986207,
"source":"USD",
"quotes":{
"USDEUR":0.828185,
"USDGBP":0.736595,
"USDCAD":1.276345,
"USDPLN":3.75205
}
}
Model class
struct Converted: Codable {
let success: Bool
let terms, privacy: String?
let timestamp: Int?
let source: String?
let quotes: [String: Double]?
}
Can someone help me to understand where I am getting wrong?. Thanks in advance.
Error messages can sometimes help. If you catch the error and print it, it reads:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))
So an array of Converted
was expected when in fact a single object was returned. The solution is to update the expectation to match the actual response:
let convertedValues = try decoder.decode(Converted.self, from: data)