How to decode nested JSON arrays using Swift Codable

I’m working with a COVID-19 API that returns nested JSON data. When I try to decode the full structure including nested arrays, it fails, but works fine when I only decode the top level fields.

Here’s the JSON response I’m getting:

[{
  "country": "USA",
  "states": [
    {
      "state": "California",
      "cases": 1250,
      "deaths": 45,
      "recovered": 200,
      "active": 1005
    }
  ],
  "lat": 39.8283,
  "lng": -98.5795,
  "lastUpdate": "2020-04-02"
}]

I created these models to parse the data:

struct CountryData: Codable {
    let country: String
    let states: [StateInfo]
}

struct StateInfo: Codable {
    let state: String
    let cases: Int
    let deaths: Int
    let recovered: Int
    let active: Int
}

The parsing works when I remove the states array from my model, but fails when I include it. Here’s my parsing code:

func loadData() {
    APIManager.shared.fetchData(endpoint: "covid-data", apiKey: "abc123") { result in
        
        guard let result = result else { return }
        
        do {
            let countries = try JSONDecoder().decode([CountryData].self, from: result)
            let firstState = countries[0].states[0].state
            self.stateName = firstState
            
            DispatchQueue.main.async {
                print(self.stateName)
            }
        } catch {
            print("Decoding failed: \(error)")
        }
    }
}

What could be causing the nested array parsing to fail? The structure looks correct to me but I must be missing something.

The issue likely arises from the incompleteness of your CountryData model. It must include the lat, lng, and lastUpdate properties present in the JSON response. When JSONDecoder finds unexpected fields in the JSON that aren’t accounted for in your struct, it results in a decoding error. To resolve this, simply update your CountryData struct to encompass all necessary fields:

struct CountryData: Codable {
    let country: String
    let states: [StateInfo]
    let lat: Double
    let lng: Double
    let lastUpdate: String
}

Alternatively, if the additional fields are unnecessary for your application, you might consider using a custom CodingKeys enum. This method allows you to selectively decode only the properties you’re interested in, thus preventing decoding errors.

Looking at your code, the decoding failure is almost certainly due to missing properties in your CountryData struct. The JSON contains lat, lng, and lastUpdate fields that aren’t defined in your model. Swift’s Codable protocol expects either all JSON keys to have corresponding properties or explicit handling of missing ones. I ran into this exact problem when working with a weather API last month. Adding the missing properties fixed it immediately. If you don’t need those extra fields, you can also implement a custom CodingKeys enum to specify exactly which properties to decode, but honestly it’s usually easier to just include all the fields from the JSON response in your struct definition.

it seems ur models don’t include all the json fields. try adding lat, lng, and lastUpdate to your CountryData struct; otherwise, the decoder might fail when it hits those extra fields.