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
相关产品推荐
相关产品推荐

