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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:15:58