Swift解析嵌套无结构JSON遇nil问题,请求解码方案
Swift中解码嵌套JSON并转换为数组的解决方案
这类嵌套JSON完全可以在Swift中解码,并且能转换为数组形式。以下是两种可行的实现方式:
1. 使用JSONSerialization(基础方式)
你的原代码使用try?会隐藏解析错误,导致返回nil而无法排查问题。下面是修复后的代码,同时将嵌套字典转换为数组:
JSON示例
{"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}}
实现代码
let jsonText = """ {"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}} """ do { guard let data = jsonText.data(using: .utf8) else { print("无法将字符串转换为Data") return } let jsonObject = try JSONSerialization.jsonObject(with: data) // 将解析结果转换为[String: [String: String]]类型的字典 guard let outerDict = jsonObject as? [String: [String: String]] else { print("JSON结构与预期不符") return } // 按外层键排序后,提取所有内层字典组成数组 let sortedKeys = outerDict.keys.sorted() let innerArray = sortedKeys.compactMap { outerDict[$0] } print("转换后的数组:\(innerArray)") } catch { print("JSON解析错误:\(error.localizedDescription)") }
2. 使用Codable协议(类型安全方式)
对于复杂JSON,推荐使用Swift的Codable协议,它提供类型安全的解码体验,同时可以自定义逻辑将字典转换为数组:
实现代码
import Foundation let jsonText = """ {"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}} """ // 自定义动态键,用于处理JSON中的字符串键 struct DynamicKey: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? { nil } init?(intValue: Int) { nil } } // 内层数据模型 struct InnerItem: Codable { let content: [String: String] init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DynamicKey.self) var contentDict = [String: String]() for key in container.allKeys { contentDict[key.stringValue] = try container.decode(String.self, forKey: key) } self.content = contentDict } } // 外层数据模型,自动转换为数组 struct OuterData: Codable { let items: [InnerItem] init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DynamicKey.self) // 按外层键排序,保证数组顺序与JSON中的键顺序一致 let sortedKeys = container.allKeys.sorted { $0.stringValue < $1.stringValue } items = try sortedKeys.map { try container.decode(InnerItem.self, forKey: $0) } } } // 解码执行 do { guard let data = jsonText.data(using: .utf8) else { print("无法转换为Data") return } let result = try JSONDecoder().decode(OuterData.self, from: data) print("Codable转换后的数组:\(result.items)") // 访问具体元素示例 if let firstItem = result.items.first { print("第一个元素的内容:\(firstItem.content)") } } catch { print("Codable解码错误:\(error.localizedDescription)") }
说明
- 两种方式都能将嵌套JSON转换为数组,其中
Codable方式更适合长期维护,类型安全且扩展性强。 - 排序步骤是可选的,如果不需要按外层键排序,可以直接提取
outerDict.values转换为数组(注意Swift字典是无序的,默认顺序不固定)。
内容的提问来源于stack exchange,提问作者PierreB
相关产品推荐
相关产品推荐

