The Bear
The Bear

Reputation: 55

Swift Codable Parsing keyNotFound

I'm having an issue getting codable going. Any help would greatly appreciated. I have the following in my playground

My JSON file

{
"metadata": {
  "generated": {
    "timestamp": 1549331723,
    "date": "2019-02-04 20:55:23"
  }
},
"data": {
    "CA": {
    "country-id": 25000,
    "country-iso": "CA",
    "country-eng": "Canada",
    "country-fra": "Canada"
    }
  }
}

I used the quicktype app to help generate the following structs

// MARK: - Welcome
struct Welcome: Codable {
    let metadata: Metadata?
    let data: DataClass?
}

// MARK: - DataClass
struct DataClass: Codable {
    let ca: CA

    enum CodingKeys: String, CodingKey {
        case ca = "CA"
    }
}

// MARK: - CA
struct CA: Codable {
    let countryID: Int
    let countryISO, countryEng, countryFra: String

    enum CodingKeys: String, CodingKey {
        case countryID = "country-id"
        case countryISO = "country-iso"
        case countryEng = "country-eng"
        case countryFra = "country-fra"
    }
}

// MARK: - Metadata
struct Metadata: Codable {
    let generated: Generated?
}

// MARK: - Generated
struct Generated: Codable {
    let timestamp: Int?
    let date: String?
}

Swift Code:

 do {
        guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else { return 0 }

        let jsonData = try Data(contentsOf: url)
        let decoder = JSONDecoder()

        let data = try decoder.decode(CA.self, from: jsonData)
        print (data)
        print(data.countryID)
        print(data.countryISO)
    } catch { print("error" , error) }

This is the error message I get.

jsonData 244 bytes
error keyNotFound(CodingKeys(stringValue: "country-id", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"country-id\", intValue: nil) (\"country-id\").", underlyingError: nil))

The value is there, I'm not sure what the issue is. If I take remove country-id from the json and model, I get the same error for country-iso.

Upvotes: 0

Views: 163

Answers (1)

David Pasztor
David Pasztor

Reputation: 54706

That's because you are trying to decode the wrong type. The CA type is nested several levels in your JSON, you need to pass the root type to JSONDecoder.decode.

let root = try decoder.decode(Welcome.self, from: jsonData)
guard let ca = root.data?.ca else { return 0 }
print(ca)

Upvotes: 1

Related Questions