Swift Codable:如何将键为交易对的JSON解码为带name属性的结构体
解决Swift中动态键JSON转带名称属性结构体的问题
你收到的JSON格式是把交易对名称作为字典的键,而你需要把这个键赋值给Pair结构体的name属性,直接用默认的Codable解码肯定行不通——毕竟默认解码逻辑会把键和结构体的固定属性绑定,而这里的键是动态变化的。下面给你两种实用的解决方案:
方法一:先解码为字典再转换(直观易维护)
这种方法先把JSON解码成字典,再遍历字典生成Pair实例,步骤清晰易懂:
- 保留你的
Pair结构体,同时定义一个辅助结构体承载每个交易对的具体数据:
struct Pair: Codable { let name: String let last: String let percentChange: String let baseVolume: String } // 辅助结构体,对应JSON里每个键的value部分 private struct PairData: Codable { let last: String let percentChange: String let baseVolume: String }
- 执行解码与转换:
// 假设你已经获取到服务器返回的JSON Data let jsonData: Data = // 你的数据来源 do { // 先解码成[String: PairData]类型,键就是交易对名称 let pairDictionary = try JSONDecoder().decode([String: PairData].self, from: jsonData) // 遍历字典,把键作为name,和数据一起生成Pair数组 let pairs = pairDictionary.map { tradePairName, data in Pair( name: tradePairName, last: data.last, percentChange: data.percentChange, baseVolume: data.baseVolume ) } // 现在pairs就是你需要的结果了 print(pairs) } catch { print("解码出错啦: \(error.localizedDescription)") }
方法二:自定义解码逻辑(封装性更强)
如果需要更优雅的封装,可以自定义一个响应结构体,把解码逻辑藏在内部,调用时直接拿到[Pair]:
struct Pair: Codable { let name: String let last: String let percentChange: String let baseVolume: String } private struct PairData: Codable { let last: String let percentChange: String let baseVolume: String } // 自定义响应结构体,处理动态键解码 struct PairsResponse: Codable { let pairs: [Pair] init(from decoder: Decoder) throws { // 创建支持动态键的容器 let keyedContainer = try decoder.container(keyedBy: DynamicCodingKey.self) var pairsArray = [Pair]() // 遍历所有动态键 for key in keyedContainer.allKeys { let data = try keyedContainer.decode(PairData.self, forKey: key) let pair = Pair( name: key.stringValue, last: data.last, percentChange: data.percentChange, baseVolume: data.baseVolume ) pairsArray.append(pair) } self.pairs = pairsArray } // 自定义动态编码键,处理字符串类型的键 private struct DynamicCodingKey: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue } let intValue: Int? init?(intValue: Int) { self.intValue = intValue self.stringValue = String(intValue) } } } // 使用方式 do { let response = try JSONDecoder().decode(PairsResponse.self, from: jsonData) print(response.pairs) } catch { print("解码失败: \(error)") }
两种方法都能解决你的问题,第一种更适合简单场景,第二种适合需要重复处理这种JSON格式的情况,按需选择即可。
内容的提问来源于stack exchange,提问作者vbb
相关产品推荐
相关产品推荐

