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

Swift使用JSONDecoder解码触发fatal error的原因及代码问题排查

错误具体含义

这个运行时崩溃是JSON解码类型不匹配直接触发的,核心错误信息翻译如下:

Swift.DecodingError.typeMismatch(类型不匹配错误):预期解码Array(数组)类型,但实际找到的是dictionary(字典/JSON对象)类型。
你代码中使用*try!强制忽略解码错误*,只要解码过程抛出异常就会直接触发Fatal Error崩溃,和你看到的Thread 7报错完全对应。

代码存在的核心问题
  • 解码目标类型和实际JSON结构不匹配:你传入的解码类型是[LandmarkLocation].self,相当于告诉解码器接口返回的JSON根节点必须是[]包裹的LandmarkLocation数组,但实际返回的JSON根节点是{}包裹的键值对字典对象(常见场景比如接口返回了带状态码、提示信息、业务数据的结构:{"code":200, "msg":"success", "data":[...]},根节点本身就是字典不是数组)。
  • 容错逻辑缺失:用try!强制处理解码结果,只要出现类型不匹配、字段缺失、数据损坏等任意解码异常,都会直接触发崩溃,没有任何排查和兜底空间。
修复方案
  • 先确认接口实际返回结构:解码前加代码打印原始JSON内容,不要凭主观预期写解码类型:
    print(String(data: dataLocation, encoding: .utf8) ?? "数据转字符串失败")
    
    • 如果根节点字典下的某个字段才是你需要的地标数组,就新建对应外层结构体遵循Decodable协议,解码外层对象后再取对应数组字段即可
    • 如果接口预期应该返回数组但实际返回了字典,大概率是请求参数错误、鉴权失败返回了错误提示对象,需要排查请求逻辑
  • 替换try!为do-catch错误处理,避免无意义崩溃,参考写法:
URLSession.shared.dataTask(with: url) { (dataLocation, _, _) in
    guard let data = dataLocation else { return }
    do {
        // 替换为和实际JSON结构匹配的解码类型
        let landmarkList = try JSONDecoder().decode([LandmarkLocation].self, from: data)
        print(landmarkList.count)
    } catch {
        print("JSON解码失败:\(error)")
    }
}
.resume()

内容的提问来源于stack exchange,提问作者Class 2346

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:54:31