Search code examples
iosjsonswiftapitype-mismatch

Type Mismatch Swift JSON


I think I created the structure correctly, but it gives error.

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))

Model:

struct veriler : Codable {
    let success : Bool
    let result : [result]
    
}

struct result : Codable {
    let country : String
    let totalCases : String
    let newCases : String
    let totalDeaths : String
    let newDeaths : String
    let totalRecovered : String
    let activeCases : String
}

JSON data:

{
  "success": true,
  "result": [
    {
      "country": "China",
      "totalcases": "80,881",
      "newCases": "+21",
      "totaldeaths": "3,226",
      "newDeaths": "+13",
      "totalRecovered": "68,709",
      "activeCases": "8,946"
    },
    {
      "country": "Italy",
      "totalcases": "27,980",
      "newCases": "",
      "totaldeaths": "2,158",
      "newDeaths": "",
      "totalRecovered": "2,749",
      "activeCases": "23,073"
    },
    "..."
  ]
}

Decoding:

let decoder = JSONDecoder()
        do {
            let country = try decoder.decode([result].self, from: data!)
          for i in 0..<country.count {
            print (country[i].country)
          }
        } catch {
          print(error)
        }

Solution

  • First you need to modify your result struct by specifying custom CodingKeys (note the mismatch between totalCases in the model and totalcases in the JSON):

    struct result: Codable {
        enum CodingKeys: String, CodingKey {
            case country, newCases, newDeaths, totalRecovered, activeCases
            case totalCases = "totalcases"
            case totalDeaths = "totaldeaths"
        }
        
        let country: String
        let totalCases: String
        let newCases: String
        let totalDeaths: String
        let newDeaths: String
        let totalRecovered: String
        let activeCases: String
    }
    

    Then you need to decode veriler.self instead of [result].self:

    let decoder = JSONDecoder()
    do {
        let result = try decoder.decode(veriler.self, from: data!)
        let countries = result.result
        for i in 0 ..< countries.count {
            print(countries[i].country)
        }
    } catch {
        print(error)
    }
    

    Note: I recommend to follow Swift guidelines and name structs like Result or Veriler (only instances should be lowercase).