致命错误:Dictionary<String, Any> 不符合 Decodable 因为 Any 不符合 Decodable

Posted

技术标签:

【中文标题】致命错误:Dictionary<String, Any> 不符合 Decodable 因为 Any 不符合 Decodable【英文标题】:Fatal error: Dictionary<String, Any> does not conform to Decodable because Any does not conform to 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。

我尝试在此 *** 页面上使用“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 数据?

【问题讨论】:

【参考方案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 是正确的方法。

以上是关于致命错误:Dictionary<String, Any> 不符合 Decodable 因为 Any 不符合 Decodable的主要内容,如果未能解决你的问题,请参考以下文章

尝试保存数组,出现错误 - 无法将类型“[Data]”的值转换为预期的参数类型“[Dictionary<String, AnyObject>]”

错误:“应解码 Dictionary<String, Any>,但找到了一个数组。” ——但我还没有定义字典? [复制]

致命错误:字符串:没有这样的文件或目录#include <string>

将 XML 转换为 Dictionary<String,String>

致命错误:string.h:没有这样的文件或目录

致命错误:改变segue