Swift使用[String: Any]解码JSON报错:No exact matches in call to instance method 'decode'
问题原因与解决方法
错误原因
你遇到的No exact matches in call to instance method 'decode'错误,本质是Swift的Decodable协议不支持直接解码[String: Any]类型。因为Any本身没有遵循Decodable协议,KeyedDecodingContainer找不到对应的decode方法来处理这个类型,所以编译器报错。
解决方案
方案1:使用明确类型替换[String: Any]
如果能确定myDictionary里存储的具体类型(比如全是字符串、数字),直接换成明确的类型即可,无需自定义init(from:):
struct MyModel: Decodable { let myDictionary: [String: String] // 替换为实际的具体类型,比如[String: Int]/[String: Double]等 private enum CodingKeys: String, CodingKey { case myDictionary } }
方案2:手动实现[String: Any]的解码逻辑
如果必须保留[String: Any],需要自定义解码逻辑,逐个判断并解析每个键值对的类型:
首先定义一个动态CodingKey用于遍历未知键:
struct DynamicCodingKey: CodingKey { var stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } }
然后扩展KeyedDecodingContainer,添加对[Any]和[String: Any]的解码支持:
extension KeyedDecodingContainer where Key == DynamicCodingKey { // 解码[Any]类型数组 func decode(_ type: [Any].self, forKey key: Key) throws -> [Any] { var arrayContainer = try nestedUnkeyedContainer(forKey: key) var array = [Any]() while !arrayContainer.isAtEnd { if let value = try? arrayContainer.decode(String.self) { array.append(value) } else if let value = try? arrayContainer.decode(Int.self) { array.append(value) } else if let value = try? arrayContainer.decode(Double.self) { array.append(value) } else if let value = try? arrayContainer.decode(Bool.self) { array.append(value) } else if let nestedDict = try? arrayContainer.decode([String: Any].self) { array.append(nestedDict) } else if let nestedArray = try? arrayContainer.decode([Any].self) { array.append(nestedArray) } } return array } // 解码[String: Any]类型字典 func decode(_ type: [String: Any].self, forKey key: Key) throws -> [String: Any] { let nestedContainer = try nestedContainer(keyedBy: DynamicCodingKey.self, forKey: key) var dict = [String: Any]() for key in nestedContainer.allKeys { if let value = try? nestedContainer.decode(String.self, forKey: key) { dict[key.stringValue] = value } else if let value = try? nestedContainer.decode(Int.self, forKey: key) { dict[key.stringValue] = value } else if let value = try? nestedContainer.decode(Double.self, forKey: key) { dict[key.stringValue] = value } else if let value = try? nestedContainer.decode(Bool.self, forKey: key) { dict[key.stringValue] = value } else if let nestedDict = try? nestedContainer.decode([String: Any].self, forKey: key) { dict[key.stringValue] = nestedDict } else if let nestedArray = try? nestedContainer.decode([Any].self, forKey: key) { dict[key.stringValue] = nestedArray } } return dict } }
最后修改MyModel的自定义解码逻辑:
struct MyModel: Decodable { let myDictionary: [String: Any] private enum CodingKeys: String, CodingKey { case myDictionary } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let nestedContainer = try container.nestedContainer(keyedBy: DynamicCodingKey.self, forKey: .myDictionary) self.myDictionary = try nestedContainer.decode([String: Any].self, forKey: DynamicCodingKey(stringValue: "")!) } }
这个方案通过遍历所有键,逐个尝试解析基础类型、嵌套字典和数组,最终构建出[String: Any]类型的实例。你可以根据实际JSON的结构,扩展更多类型的解析逻辑(比如日期、枚举等)。
内容的提问来源于stack exchange,提问作者soso22
相关产品推荐
相关产品推荐

