Swift中JSON解码失败排查:验证JSON与结构体后仍报错
JSON解码失败排查方案
问题描述
尝试解码JSON数据时,始终在解码步骤报错,已验证JSON格式和Codable结构体均无问题,询问遗漏的排查点。
相关代码
JsonManager.swift
extension Bundle { func decode (_ file: String) -> Cities { guard let url = self.url(forResource: file, withExtension: nil) else { fatalError("Failed to locate \(file) in bundle") } guard let data = try? Data(contentsOf: url) else { fatalError("failed to load \(file) bundle") } let decoder = JSONDecoder() guard let loaded = try? decoder.decode(Cities.self, from: data) else { fatalError("Failed to decode \(file) from bundle") // (Run time error here) Fatal error: Failed to decode cities.json from bundle } print("loaded") return loaded } }
ContentView.swift
var cities = Bundle.main.decode("cities.json")
cities.json
{ "city": [ { "id": "1", "name": "Mumbai", "state": "Maharashtra" }, { "id": "2", "name": "Delhi", "state": "Delhi" } ] }
JsonStruct.swift
struct Cities: Codable { struct City: Codable { let id: String let name: String let state: String } let city: [City] }
排查与解决步骤
捕获具体解码错误
当前代码用try?会吞掉所有错误信息,无法定位问题。把解码部分改成do-catch块,打印详细错误:let decoder = JSONDecoder() do { let loaded = try decoder.decode(Cities.self, from: data) print("loaded") return loaded } catch { fatalError("Failed to decode \(file) from bundle: \(error)") }运行后就能看到具体错误,比如键名不匹配、类型不兼容、JSON编码问题等。
修正Bundle文件查找逻辑
调用decode("cities.json")时,方法里用url(forResource: file, withExtension: nil),会查找文件名完全为"cities.json"且无扩展名的文件,但实际文件是cities.json(文件名cities,扩展名json)。可以修改调用方式为Bundle.main.decode("cities"),同时把方法里的withExtension改为"json":guard let url = self.url(forResource: file, withExtension: "json") else { fatalError("Failed to locate \(file).json in bundle") }这样更符合Bundle文件查找的常规逻辑。
验证JSON文件属性
- 确认JSON文件已添加到当前Target的
Target Membership(选中文件,右侧面板勾选对应Target); - 检查JSON文件编码是否为UTF-8(Xcode中选中文件,右侧面板查看
Text Encoding),非UTF-8编码可能导致Data加载异常。
- 确认JSON文件已添加到当前Target的
确认结构体与JSON匹配
当前结构体定义和JSON结构是匹配的,但如果后续JSON有修改,要确保键名完全一致(区分大小写),属性类型匹配(比如JSON里的id是字符串,结构体里也是String,这点没问题)。
内容的提问来源于stack exchange,提问作者Hitesh Suthar
相关产品推荐
相关产品推荐

