JSONDecoder无法解码嵌套字典

时间:2019-03-26 14:34:12

标签: ios json swift swift4 jsondecoder

我正在使用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)
            }
        }
  1. 模型如下:
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
    }
}

  1. 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 个答案:

答案 0 :(得分:3)

JSON参数“ key”不是整数。

将其更改为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
    }
}

答案 1 :(得分:0)

您可以切换到手动解码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,因为这正是您真正想要的。