【问题标题】:Fatal error: Dictionary<String, Any> does not conform to Decodable because Any does not conform to Decodable致命错误:Dictionary<String, Any> 不符合 Decodable 因为 Any 不符合 Decodable
【发布时间】:2018-08-07 16:09:26
【问题描述】:

我正在尝试使用 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。

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

【问题讨论】:

    标签: ios json swift swift4 decodable


    【解决方案1】:

    我使用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
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      在您的情况下,您可能会创建一个类似的结构

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

      并解码 JSON

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

      任何崩溃都会显示设计错误。在主包中的文件中使用null 的意义是另一个问题。

      【讨论】:

      • 啊,这是有道理的,这样设置时它的工作原理。谢谢!
      • 请注意,您可以为两个let colors = try! JSONDecoder().decode(Something.self, from: Data(contentsOf: url)) 使用一个try
      • 在大多数情况下我们只需要一个通用的解决方案,给我一个字典或其他类型只包含内置类型,我们不想为每个 json 文件创建一个符合 Decodable 的类。也许 JSONSerialization 是正确的方法。
      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 2018-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      相关资源
      最近更新 更多