Swift中关联类型传递Codable对象及JSON解码失败问题求助
解决Codable解码错误:数据无法读取(缺失)的问题
问题根源分析
你遇到的解码错误,本质是泛型类型的解码期望和实际JSON结构不匹配:
当你使用Resource<CurrencyModel>时,解码器会默认认为JSON根节点的quotes字段是一个包含quotes子字段的对象(也就是期望结构是{"quotes": {"quotes": {...}}}),但实际API返回的JSON里,quotes直接就是一个[String: Double]字典,没有额外嵌套。解码器找不到它期望的quotes.quotes路径,就抛出了“数据缺失”的错误。
解决方案
方案1:直接使用字典作为泛型类型(最简单)
如果你只是想把汇率数据泛型化处理,不需要额外的CurrencyModel,直接用[String: Double]作为T即可,这和你最初工作的逻辑完全一致:
// 调用方式调整为: CurrencyLayerCommunicator().get(Resource<[String: Double]>.self) { [weak self] item in self?.handleResult(item) }
方案2:调整CurrencyModel适配字典解码
如果你确实需要单独的模型封装汇率数据,可以通过自定义解码逻辑,让CurrencyModel直接解析quotes的字典结构:
struct CurrencyModel: Decodable { let rates: [String: Double] // 自定义解码:把传入的字典直接映射到rates属性 init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() rates = try container.decode([String: Double].self) } } // 调用方式不变,现在能正确解析: CurrencyLayerCommunicator().get(Resource<CurrencyModel>.self) { [weak self] item in self?.handleResult(item) }
如果想让数据结构更友好(比如把键值对转换成单独的汇率模型),可以进一步扩展:
// 单个汇率模型 struct CurrencyRate: Decodable { let currencyPair: String // 比如"USDBAM" let rate: Double } // 封装所有汇率的模型 struct CurrencyModel { let rates: [CurrencyRate] } // 实现Decodable,把字典转成数组 extension CurrencyModel: Decodable { init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let quotesDict = try container.decode([String: Double].self) rates = quotesDict.map { CurrencyRate(currencyPair: $0.key, rate: $0.value) } } } // 调用方式依然是Resource<CurrencyModel>
关键总结
核心是让泛型参数T的解码逻辑和API返回的quotes字段类型完全匹配:要么直接用字典类型,要么让自定义模型能正确解析字典数据,避免不必要的嵌套期望。
内容的提问来源于stack exchange,提问作者MMI Test
相关产品推荐
相关产品推荐

