如何在Swift中解析包含双层嵌套无键数组的JSON文件(Xcode 10.1、macOS环境)
Swift解析嵌套动态键JSON的完整指南
嘿,刚上手Swift和JSON解析确实容易被这种嵌套结构搞晕,尤其是遇到"3600"这种动态键+双层无键数组的情况,别慌,我一步步带你搞定~
第一步:先理清JSON结构
先把你给的JSON拆解开看,这样更容易对应Swift模型:
{"result":{"3600":[[1619589600,54894.2,55019.7,54515,54660.8,104.41723222,5713178.066847375]] }, "allowance":{"cost":0, "remaining":10, "remainingPaid":9999999999, "account":"cccccc6758e98d700f" }}
- 顶层有两个核心字段:
result和allowance allowance是常规键值对,很好处理result里的键是动态的(比如这里的3600,可能还有其他数字键),对应的值是双层数组:外层是数组,内层数组里是一组有序的数值(时间戳、价格、成交量等)
第二步:定义Swift模型(Codable方案)
Swift的Codable协议是解析JSON的最优解,咱们针对这个结构定义对应的结构体:
1. 先处理内层的数值数组
内层数组里的元素是固定顺序的:时间戳(Int)、开盘价(Double)、最高价(Double)、最低价(Double)、收盘价(Double)、成交量(Double)、成交额(Double)。咱们可以创建一个结构体来封装这些值,手动实现Codable来解析数组:
struct CandleData: Codable { let timestamp: Int let open: Double let high: Double let low: Double let close: Double let volume: Double let turnover: Double // 手动实现数组转结构体的解码逻辑 init(from decoder: Decoder) throws { var container = try decoder.unkeyedContainer() timestamp = try container.decode(Int.self) open = try container.decode(Double.self) high = try container.decode(Double.self) low = try container.decode(Double.self) close = try container.decode(Double.self) volume = try container.decode(Double.self) turnover = try container.decode(Double.self) } // 如果需要编码的话也可以实现encode(to:),仅解析用可暂时忽略 }
2. 定义顶层模型
针对result的动态键,咱们用[String: [CandleData]]来表示(键是动态字符串,值是CandleData的数组);allowance直接用结构体表示:
struct Allowance: Codable { let cost: Int let remaining: Int let remainingPaid: Int let account: String } struct ApiResponse: Codable { let result: [String: [CandleData]] let allowance: Allowance }
第三步:编写解析代码
假设你已经把JSON内容读取成了Data(比如从本地文件或者网络请求获取),接下来就可以解码了:
// 示例:从本地JSON文件读取数据 guard let url = Bundle.main.url(forResource: "yourJsonFile", withExtension: "json"), let data = try? Data(contentsOf: url) else { print("无法读取JSON文件") return } // 解码JSON do { let decoder = JSONDecoder() let response = try decoder.decode(ApiResponse.self, from: data) // 拿到解析后的数据 print("剩余免费请求次数:\(response.allowance.remaining)") // 遍历result里的动态键和对应的数据 for (timeCycle, candleList) in response.result { print("当前时间周期:\(timeCycle)") for candle in candleList { print("时间戳:\(candle.timestamp),收盘价:\(candle.close)") } } } catch { print("解码失败:\(error.localizedDescription)") }
关键注意点
- 如果
result里的动态键(比如3600)是固定含义的时间周期,你也可以用枚举来映射,但如果是完全动态的,用[String: [CandleData]]是最灵活的方案 - 内层数组的顺序一定要和JSON里的元素顺序完全对应,不然会解码失败
- 如果JSON里的数值可能出现
null,记得把模型里的属性改成可选类型(比如let timestamp: Int?)
内容的提问来源于stack exchange,提问作者Matthes
相关产品推荐
相关产品推荐

