Swift Codable Parsing keyNotFound

Sep 09 2020

У меня проблема с кодированием. Любая помощь будет принята с благодарностью. У меня на детской площадке есть следующее

Мой файл JSON

{
"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"
    }
  }
}

Я использовал приложение quicktype, чтобы создать следующие структуры

// 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?
}

Быстрый код:

 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) }

Это сообщение об ошибке, которое я получаю.

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))

Ценность есть, я не уверен, в чем проблема. Если я удаляю идентификатор страны из json и модели, я получаю ту же ошибку для страны-iso.

Ответы

1 DávidPásztor Sep 09 2020 at 13:56

Это потому, что вы пытаетесь декодировать неправильный тип. CAТип вложен несколько уровней в вашем JSON, вам нужно передать корневой тип в JSONDecoder.decode.

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