JSONDecoder не удалось декодировать вложенные словари - PullRequest
0 голосов
/ 26 марта 2019

Я использую JSONDecoder для декодирования из файла JSON с вложенными словарями.Он не может декодировать данные json в мою настроенную модель.

Это то, что я пробовал в своем коде.

  1. Код JSONDecoder выглядит следующим образом:
let netWorkManager = NetWorkManager(URL: url, httpMethodType: .GET)
        netWorkManager.callAPI { (data, status, error) in
            guard let data = data else {
                onFail(NetWorkError.otherError)
                return
            }

            switch status {
            case 200:
                do{
                    if let responseModel = try JSONDecoder().decode(ResonseModel?.self, from: data) {
                        onSuccess(responseModel)
                    }
                }catch {
                    onFail(NetWorkError.otherError)
                }
            default:
                onFail(NetWorkError.otherError)
            }
        }
Модель выглядит так:
struct ResonseModel: Codable {
    let type : String
    let format: String
    let data: [String: Champion]

    struct Champion: Codable {
        let version: String
        let id: String
        let key: Int
        let name: String
        let title: String
        let blurb: String
    }
}

Структура JSON выглядит следующим образом:
{
    "type": "champion",
    "format": "standAloneComplex",
    "version": "9.3.1",
    "data": {
        "Aatrox": {
            "version": "9.3.1",
            "id": "Aatrox",
            "key": "266",
            "name": "Aatrox",
            "title": "the Darkin Blade",
            "blurb": "Once honored defenders of Shurima against the Void, Aatrox and his brethren would eventually become an even greater threat to Runeterra, and were defeated only by cunning mortal sorcery. But after centuries of imprisonment, Aatrox was the first to find...",
            "info": {
                "attack": 8,
                "defense": 4,
                "magic": 3,
                "difficulty": 4
            },
            "tags": [
                "Fighter",
                "Tank"
            ],
            "partype": "Blood Well",

        },
        "Ahri": {
            "version": "9.3.1",
            "id": "Ahri",
            "key": "103",
            "name": "Ahri",
            "title": "the Nine-Tailed Fox",
            "blurb": "Innately connected to the latent power of Runeterra, Ahri is a vastaya who can reshape magic into orbs of raw energy. She revels in toying with her prey by manipulating their emotions before devouring their life essence. Despite her predatory nature...",
            "info": {
                "attack": 3,
                "defense": 4,
                "magic": 8,
                "difficulty": 5
            },

            "tags": [
                "Mage",
                "Assassin"
            ],
            "partype": "Mana",

        },
        ...

это ссылка на JSON, если вы хотите посмотреть на нее: http://ddragon.leagueoflegends.com/cdn/9.3.1/data/en_US/champion.json

Я хочу декодироватьсвойство data в качестве словаря, ключом которого является имя чемпиона, а значением - чемпион.Но jsonDecoder, похоже, не распознает структуру моей модели.В конце концов поймать ошибку.

Ответы [ 2 ]

3 голосов
/ 26 марта 2019

JSON-параметр "ключ" не является целым числом.

Измените его на String, и он будет работать:

struct ResonseModel: Codable {
    let type : String
    let format: String
    let data: [String: Champion]

    struct Champion: Codable {
        let version: String
        let id: String
        let key: String
        let name: String
        let title: String
        let blurb: String
    }
}
0 голосов
/ 26 марта 2019

Вы можете переключиться на ручное декодирование Champion для очистки данных.

struct ResonseModel: Decodable {
    let type : String
    let format: String
    let data: [String: Champion]

    struct Champion: Decodable {
        let version: String
        let id: String
        let key: Int
        let name: String
        let title: String
        let blurb: String

        enum CodingKeys: String, CodingKey {
            case version, id, key, name, title, blurb
        }

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.version = try container.decode(String.self, forKey: .version)
            self.id = try container.decode(String.self, forKey: .id)
            guard let key = Int(try container.decode(String.self, forKey: .key)) else {
                throw DecodingError.valueNotFound(Int.self,
                                                  .init(codingPath: decoder.codingPath,
                                                        debugDescription: "Bad value for id"))
            }
            self.key = key
            self.name = try container.decode(String.self, forKey: .name)
            self.title = try container.decode(String.self, forKey: .title)
            self.blurb = try container.decode(String.self, forKey: .blurb)
        }
    }
}

Это в основном код, который компилятор пишет для вас;он просто конвертирует строку в int, потому что это то, что вы действительно хотели.

...