致命错误:Dictionary <string,any =“”>不符合Decodable,因为Any不符合Decodable

时间:2018-02-27 21:40:32

标签: ios json swift swift4 decodable

我试图使用swift 4来解析本地json文件:

{
    "success": true,
    "lastId": null,
    "hasMore": false,
    "foundEndpoint": "https://endpoint",
    "error": null
}

这是我使用的功能:

    func loadLocalJSON() {

        if let path = Bundle.main.path(forResource: "localJSON", ofType: "json") {
            let url = URL(fileURLWithPath: path)

            do {
                let data  = try Data(contentsOf: url)
                let colors = try JSONDecoder().decode([String: Any].self, from: data)
                print(colors)
            }
            catch { print("Local JSON not loaded")}
        }
    }
}

但我一直收到错误:

  

致命错误:词典不符合Decodable   因为Any不符合Decodable。

我尝试使用&#34; AnyDecodable&#34;此stackoverflow页面上的方法:How to decode a property with type of JSON dictionary in Swift 4 decodable protocol 但它会跳到“赶上”的地步。声明:catch { print("Local JSON not loaded")使用时。有谁知道如何在Swift 4中解析这个JSON数据?

2 个答案:

答案 0 :(得分:4)

我使用quicktype生成Codables和编组代码:

https://app.quicktype.io?gist=02c8b82add3ced7bb419f01d3a94019f&l=swift

我根据您的样本数据给出了一系列样本:

[
  {
    "success": true,
    "lastId": null,
    "hasMore": false,
    "foundEndpoint": "https://endpoint",
    "error": null
  },
  {
    "success": true,
    "lastId": 123,
    "hasMore": false,
    "foundEndpoint": "https://endpoint",
    "error": "some error"
  }
]

这告诉quicktype假设您的第一个示例中的null值有时是IntString - 如果它们不是可能的类型,您可以更改这些值。生成的Codable是:

struct Local: Codable {
    let success: Bool
    let lastID: Int?
    let hasMore: Bool
    let foundEndpoint: String
    let error: String?

    enum CodingKeys: String, CodingKey {
        case success
        case lastID = "lastId"
        case hasMore, foundEndpoint, error
    }
}

答案 1 :(得分:3)

也许你误解了Codable的工作原理。它基于具体类型。

在您的情况下,您可以创建一个类似

的结构
Any

解码JSON

struct Something: Decodable {
    let success : Bool
    let lastId : Int?
    let hasMore: Bool
    let foundEndpoint: URL
    let error: String?
}

任何崩溃都会泄露设计错误。在主包中的文件中使用func loadLocalJSON() { let url = Bundle.main.url(forResource: "localJSON", withExtension: "json")! let data = try! Data(contentsOf: url) let colors = try! JSONDecoder().decode(Something.self, from: data) print(colors) } 的意义是另一个问题。