Swift中遍历解码后JSON字典键,提取加密货币符号并遍历数据
解决Swift中CMC API多层嵌套JSON的遍历与模型重构问题
首先明确说:重构现有模型绝对是最优方案——你当前的模型依赖硬编码的币种ID(比如"1"对应BTC)来单独访问,扩展性极差,新加任何币种都得修改代码,完全不符合API返回的动态结构。重构后不仅能灵活处理任意返回的加密货币,还能让代码更清晰、易维护。
第一步:重构Codable模型
先修正你的模型结构,让它能完整解析CMC API返回的所有需要字段,同时适配动态的币种ID键:
// 统一表示单个加密货币的所有信息 struct CryptoCurrency: Codable { let id: Int64 let name: String let symbol: String let maxSupply: Double? let quotes: [String:Quote] // 处理JSON蛇形命名到Swift驼峰命名的映射 enum CodingKeys: String, CodingKey { case id, name, symbol, quotes case maxSupply = "max_supply" } } // 报价信息(比如USD) struct Quote: Codable { let price: Double let marketCap: Double enum CodingKeys: String, CodingKey { case price case marketCap = "market_cap" } } // 顶层响应模型 struct ServerResponse: Codable { let data: [String:CryptoCurrency] }
这个重构后的模型去掉了原来硬编码的btc/eth属性,直接用[String:CryptoCurrency]来接收所有返回的币种——键是CMC的币种ID,值是对应的完整信息,完美适配API的结构。
第二步:遍历与数据处理
针对你的两个需求,分别说下实现方式:
1. 提取所有加密货币符号
用map方法最简洁,一行代码就能搞定:
do { let decoder = JSONDecoder() // 全局设置自动转换蛇形命名到驼峰,省去每个模型写CodingKeys的麻烦 decoder.keyDecodingStrategy = .convertFromSnakeCase let response = try decoder.decode(ServerResponse.self, from: yourJsonData) // 提取所有币种符号 let allSymbols = response.data.values.map { $0.symbol } print(allSymbols) // 输出 ["BTC", "ETH", ...] } catch { print("JSON解析失败: \(error.localizedDescription)") }
2. 生成表格视图所需数据
这里可以用compactMap把原始数据转换成表格单元格专用的模型(避免直接在表格里处理原始数据,提升代码可读性):
先定义表格单元格的模型:
struct CryptoCellModel { let symbol: String let name: String let marketCap: String let maxSupply: String }
然后转换数据:
do { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let response = try decoder.decode(ServerResponse.self, from: yourJsonData) let cellModels = response.data.values.compactMap { crypto -> CryptoCellModel? in // 确保有USD报价和maxSupply数据,避免空值崩溃 guard let usdQuote = crypto.quotes["USD"], let maxSupply = crypto.maxSupply else { return nil } // 格式化数值,让表格显示更友好 let formattedMarketCap = String(format: "$%.2f", usdQuote.marketCap) let formattedMaxSupply = String(format: "%.0f", maxSupply) return CryptoCellModel( symbol: crypto.symbol, name: crypto.name, marketCap: formattedMarketCap, maxSupply: formattedMaxSupply ) } // 现在cellModels就是表格的数据源,可以直接赋值给tableView的dataSource数组 } catch { print("解析错误: \(error)") }
如果需要逐个处理每个币种(比如做一些额外的业务逻辑,比如过滤特定排名的币种),for-in循环会更直观:
for (cryptoId, crypto) in response.data { print("处理币种ID: \(cryptoId)") if crypto.symbol == "BTC" { // 针对BTC的特殊处理 } // 其他通用逻辑 }
总结
- 模型重构是必须的:它解决了硬编码带来的扩展性问题,让你的代码能适配API返回的任意币种,同时符合Swift Codable的最佳实践。
- 遍历方式选择:
- 快速提取或转换数据用
map/compactMap,代码更简洁; - 需要复杂逻辑处理每个元素时用
for-in循环,可读性更强。
- 快速提取或转换数据用
内容的提问来源于stack exchange,提问作者Edison
相关产品推荐
相关产品推荐

