Swift解析数组型JSON转NSArray仅输出[字符的解决方法
问题描述
我有一个根节点为数组、内部存储多个地点信息字典的JSON文件,结构如下:
[ { "tn_newsid": 144377, "tn_midashi": "知床半島とオホーツク海の絶景が広がる", "tn_name": "北海道立オホーツク公園オートキャンプ場てんとらんど", "tn_ktel": "0152-45-27", "tn_url": "", "tn_kdo": 144.239526856306, "tn_ido": 43.9880220633556, "tn_im1name": "144377_1.jpg", "tn_im2name": "144377_2.jpg", "tn_im3name": "144377_3.jpg", "tn_im4name": "144377_4.jpg", "type": 0, "nico_recommended": 0 }, { // 其余地点数据 } ]
最初实现解析逻辑时,错误将JSONSerialization的解析结果强转为Dictionary<String,Any>,代码片段如下:
seasonInfoService.seasonServerDataJson(jsoncompleted: { () in let responseData: Data = self.seasonInfoService.UpdateJsonString.data(using: String.Encoding.utf8)! do{ let items = try JSONSerialization.jsonObject(with: responseData) as! Dictionary<String,Any>
由于JSON文件根节点是数组(以[开头),运行时直接抛出类型转换错误:
Could not cast value of type '__NSArrayI' (0x7fff86cd0128) to 'NSDictionary'
后续将强转类型修改为NSArray,调整后代码如下:
facilitiesService.facilitiesServerDataJson(urlToFetch: url_, jsoncompleted: { () in let responseData: Data = self.facilitiesService.UpdateJsonString.data(using: String.Encoding.utf8)! do{ let items = try JSONSerialization.jsonObject(with: responseData) as! NSArray print(items)
但执行print语句时控制台仅输出[,无法获取由字典组成的完整数组。
解决方案
控制台仅输出[的核心原因不是类型转换写法错误,首先要排查数据源完整性,再调整解析逻辑的安全性:
- 第一步:校验原始JSON字符串完整性
先打印self.facilitiesService.UpdateJsonString的全量内容和字符长度,90%以上的同类问题是接口返回/本地读取的JSON字符串本身被截断,仅拿到了开头的[符号,没有获取到完整的数组内容。如果数据源不完整,优先修复网络请求、文件读取或字符串拼接逻辑,拿到完整合法的JSON字符串后再做解析。 - 第二步:替换为Swift原生类型做安全解析,不要使用
NSArray/NSDictionary等Objective-C遗留类型,同时移除所有强制解包(!)逻辑,避免运行时崩溃,参考写法如下:
facilitiesService.facilitiesServerDataJson(urlToFetch: url_, jsoncompleted: { [weak self] in guard let self = self else { return } // 安全转换Data,不做强制解包 guard let responseData = self.facilitiesService.UpdateJsonString.data(using: .utf8) else { print("JSON字符串转Data失败,请检查编码格式") return } do { // 根节点为字典组成的数组,直接转换为Swift原生[[String: Any]]类型 guard let items = try JSONSerialization.jsonObject(with: responseData) as? [[String: Any]] else { print("JSON结构不符合预期,根节点不是字典数组") return } print("解析完成,共获取\(items.count)个地点信息") // 遍历数组读取单个地点字段 for location in items { let locationName = location["tn_name"] as? String ?? "" let latitude = location["tn_ido"] as? Double ?? 0 let longitude = location["tn_kdo"] as? Double ?? 0 print("地点:\(locationName),坐标:\(latitude), \(longitude)") } } catch { print("JSON解析失败,错误信息:\(error.localizedDescription)") } })
- 第三步:如果确认JSON字符串完整但仍解析异常,可将
responseData重新转换为字符串打印,检查是否存在BOM头、不可见特殊字符导致JSON合法性校验失败。
内容的提问来源于stack exchange,提问作者Kopera Marcel
相关产品推荐
相关产品推荐

