Reputation: 63
I am trying to call an API that has an array of dictionaries: I Got the error below and not sure how I can fix. This is my struct model
struct Countries : Codable {
var countries : [Country]
}
struct Country : Codable {
var Country : String
var NewConfirmed : Int
var TotalConfirmed : Int
var NewDeaths : Int
var TotalDeaths : Int
var NewRecovered : Int
var TotalRecovered : Int
var CountryCode : String
}
This is my networking code :
class Networking {
func response (url: String , completion: @escaping (Countries) -> ()) {
guard let url = URL(string: url) else {return}
URLSession.shared.dataTask(with: url, completionHandler: { (data , response , error ) in
self.urlCompletionHandler(data: data, response: response, error: error, completion: completion)
}).resume()
}
func urlCompletionHandler (data: Data? , response : URLResponse? , error : Error? , completion: (Countries) -> ()) {
guard let data = data else {return}
do {
let jsondecoder = JSONDecoder()
let countries = try jsondecoder.decode(Countries.self, from: data)
completion(countries)
} catch {
print("Error \(error)")
}
}
}
And this is my call in the controller :
func response () {
newtorkhanler.response(url: UrlPathSingleTon.urlsingleton.shared()) { (countried : (Countries)) in
self.countrizs = countried.countries
DispatchQueue.main.async {
self.tableview.reloadData()
}
}
I want to populate an array of Country that I made it as an array variable inside Countries struct. My plan is to decode the Countries and use its array variable of Country that I named countries and set to the countrizs
array of Country inside response function. I get this error that is specific to the countries variable inside the Countries struct :
Error keyNotFound(CodingKeys(stringValue: "countries", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"countries\", intValue: nil) (\"countries\").", underlyingError: nil))
And this is the API json format: the array JSON data is in the attached pic:
{
"Countries": [
{
"Country": "Afghanistan",
"CountryCode": "AF",
"Slug": "afghanistan",
"NewConfirmed": 787,
"TotalConfirmed": 18054,
"NewDeaths": 6,
"TotalDeaths": 300,
"NewRecovered": 63,
"TotalRecovered": 1585,
"Date": "2020-06-05T17:51:15Z"
},
{
"Country": "Albania",
"CountryCode": "AL",
"Slug": "albania",
"NewConfirmed": 13,
"TotalConfirmed": 1197,
"NewDeaths": 0,
"TotalDeaths": 33,
"NewRecovered": 0,
"TotalRecovered": 898,
"Date": "2020-06-05T17:51:15Z"
}
]
}
Upvotes: 0
Views: 188
Reputation: 16341
To fix this issue you need to modify your property from countries
to Countries
. Your keys should match the keys in the JSON
.
struct Countries : Codable {
var Countries : [Country]
}
Or you could make the property name lowercased and the struct uppercased Swift style like this:
struct Countries : Codable {
var countries : [Country]
enum CodingKeys: String, CodingKey {
case countries = "Countries"
}
}
Upvotes: 1
Reputation: 1475
If your var names vary from the names of the keys in your json, you can define your coding keys explicitly so they match up (otherwise, when all properties are already Decodable
, your coding keys will be synthesized).
struct Countries : Codable {
var countries : [Country]
enum CodingKeys: String, CodingKey {
case countries = "Countries"
}
}
Note your cases must match up to the names of the vars you are trying to decode. The compiler will enforce this, and your object won't conform to Decodable
(or Encodable) while you have properties without matching cases in your CodingKeys
enum.
This way, you can maintain your naming conventions.
Upvotes: 1