You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:15:30