Swift Codable解码报错:期望Dictionary<String, Any>却得到数组
解决Codable解码JSON时的typeMismatch错误
咱们先拆解下你遇到的错误提示:
typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "txt_forecast", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))
这个错误说得非常直白:你在解析txt_forecast字段时,错误地把它当成了字典处理,但实际上它对应的JSON值是一个数组,类型不匹配自然就抛出了错误。
再看你的代码,问题主要集中在这几点:
- 手动嵌套解析的逻辑完全错误,把数组类型的字段当成字典来创建嵌套容器
- 多做了一次没必要的
JSONDecoder二次解码,原始解码器已经在处理整个JSON数据了 - CodingKeys的定义把不同层级的key混在一起,导致解析路径混乱
下面是修正后的代码,完全匹配JSON结构,且利用Codable的自动解码能力,简洁又不易出错:
// 顶层容器结构体,对应JSON最外层对象 struct WeatherContainer: Decodable { let forecast: Forecast } // 对应JSON里forecast字段的结构体 struct Forecast: Decodable { // txt_forecast是数组,直接定义为ForecastDay类型的数组 let txt_forecast: [ForecastDay] } // 每日预报的结构体,匹配数组里的每个元素 struct ForecastDay: Decodable { let period: Int let icon: String let title: String let fcttext: String // 因为字段名和JSON完全一致,所以可以省略CodingKeys,Codable会自动映射 // 后续如果需要修改字段名,再添加CodingKeys即可 }
对应的解码调用代码:
// 假设你已经通过网络请求或其他方式获取到了JSON数据data do { let weatherData = try JSONDecoder().decode(WeatherContainer.self, from: data) let forecastDays = weatherData.forecast.txt_forecast print(forecastDays) } catch { print("解码失败:\(error.localizedDescription)") }
额外提醒:
- Swift的类型命名规范是首字母大写(比如
ForecastDay而非forecastday),能大幅提升代码可读性 - 除非有特殊的自定义解码需求,尽量不要手动实现
init(from:),Codable的自动解码已经能覆盖绝大多数场景,减少出错概率 - 解码前一定要仔细确认JSON的层级结构,搞清楚每个字段对应的类型是字典还是数组,这是解码时最容易踩坑的地方
内容的提问来源于stack exchange,提问作者Bilbo Baggins
相关产品推荐
相关产品推荐

