Swift解析CoinGecko API时JSON值始终返回nil问题排查
我来帮你排查下问题所在,你的代码里有几个关键错误导致解析失败、返回nil:
问题分析
结构体层级与JSON完全不匹配
API返回的最外层是一个包含data字段的对象,而data本身也是单个对象(不是数组),但你定义的GlobalData里data是[GlobalMarketCap]数组,这完全错误。另外,total_market_cap是键值对对象(比如{"usd": xxx, "aud": xxx}),不是数组,但你把它定义成了[currencyMarketCap]数组,这会直接导致解析失败。解码目标错误
你直接尝试解码currencyMarketCap类型,但API返回的JSON最外层是包含data的完整结构,跳过外层直接解码内层类型肯定无法匹配。数据类型不匹配
total_market_cap里的所有数值都是浮点型(比如492128933231.6131),但你结构体里eur定义为Int?、aud是Float?,类型不匹配会导致这些字段被置为nil,甚至整个解析流程失败。自定义init干扰自动解码
你给GlobalData添加了自定义init,但没有实现Decodable对应的初始化逻辑,破坏了Swift自动合成的解码方法,导致解析异常。
修正后的代码
首先是匹配JSON结构的结构体定义:
// 对应API返回的最外层JSON结构 struct GlobalResponse: Decodable { let data: GlobalData } // 对应data字段的内容 struct GlobalData: Decodable { let active_cryptocurrencies: Int let markets: Int let total_market_cap: CurrencyMarketCap // 如需其他字段,可继续添加(比如total_volume、updated_at等) } // 对应total_market_cap的币种市值数据,统一用Double适配浮点数值 struct CurrencyMarketCap: Decodable { let usd: Double? let aud: Double? let eur: Double? let jpy: Double? }
然后是修正后的请求解码代码:
func globalMarket() { guard let requestURL = URL(string: "https://api.coingecko.com/api/v3/global") else { print("无效的URL地址") return } let request = URLRequest(url: requestURL) let requestTask = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("请求错误: \(error.localizedDescription)") return } guard let data = data else { print("未接收到返回数据") return } do { // 从最外层结构开始逐层解码 let globalResponse = try JSONDecoder().decode(GlobalResponse.self, from: data) let marketCap = globalResponse.data.total_market_cap print("当前各币种市值: \(marketCap)") // 单独访问某一币种市值示例 if let usdCap = marketCap.usd { print("美元总市值: $\(usdCap)") } } catch { // 打印具体解码错误,方便后续排查 print("解析失败: \(error)") } } requestTask.resume() }
额外说明
- 我把结构体命名改成了Swift规范的大驼峰格式(比如
CurrencyMarketCap而非currencyMarketCap),这是Swift开发的最佳实践。 - 移除了不必要的自定义
init,让Swift自动合成Decodable的解码逻辑。 - 所有数值类型统一用
Double,完美适配API返回的浮点型数据。 - 增加了空值判断和详细错误打印,方便你快速定位后续可能出现的问题。
内容的提问来源于stack exchange,提问作者Tim Kruger
相关产品推荐
相关产品推荐

