You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift解析CoinGecko API时JSON值始终返回nil问题排查

我来帮你排查下问题所在,你的代码里有几个关键错误导致解析失败、返回nil:

问题分析

  1. 结构体层级与JSON完全不匹配
    API返回的最外层是一个包含data字段的对象,而data本身也是单个对象(不是数组),但你定义的GlobalData里data是[GlobalMarketCap]数组,这完全错误。另外,total_market_cap是键值对对象(比如{"usd": xxx, "aud": xxx}),不是数组,但你把它定义成了[currencyMarketCap]数组,这会直接导致解析失败。

  2. 解码目标错误
    你直接尝试解码currencyMarketCap类型,但API返回的JSON最外层是包含data的完整结构,跳过外层直接解码内层类型肯定无法匹配。

  3. 数据类型不匹配
    total_market_cap里的所有数值都是浮点型(比如492128933231.6131),但你结构体里eur定义为Int?、aud是Float?,类型不匹配会导致这些字段被置为nil,甚至整个解析流程失败。

  4. 自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:15:20