API 获取 returns 无

API Fetch returns nil

获取没有抛出任何错误,它只是 returns nil,我不知道为什么,这是 api URL:

https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true&include_last_updated_at=true

注意:代币的数量是无限的,不仅仅是比特币,所以我不能硬编码。

看起来像:

{
    "bitcoin": {
        "usd": 51110,
        "usd_market_cap": 964544028181.903,
        "usd_24h_vol": 19080677597.123028,
        "usd_24h_change": 2.163373654971005,
        "last_updated_at": 1640575480
    },
    thereCanBeMoreWhichIcan'tPredict: {
        ...
    }
}

这是我创建的模型:

struct TokenSimplePriceCoingeckoUsdModel: Codable, Hashable {
    let usd, usd_market_cap, usd_24h_vol, usd_24h_change: Double?
    let last_updated_at: Int?
}

这就是我使用 Alamofire 获取它的方式:

func afRequest(url: URL) async throws -> Data {
    try await withUnsafeThrowingContinuation { continuation in
        // If another error try lowering the request error: (statusCode: 200..<300)
        // timeoutInterval is in seconds
        AF.request(url, method: .get, requestModifier: { [=15=].timeoutInterval = .infinity }).validate(statusCode: 200..<600).responseData { response in
            
            if let data = response.data {
                continuation.resume(returning: data)
                return
            }
            
            if case let .failure(error) = response.result {
                print(" Error on afRequest(): \(error)")
                continuation.resume(throwing: error)
                return
            }
        }
    }
}

func getDataFromAPI(url: String) async -> Any {
    do {
        let url = URL(string: url)!
        let undecodedData = try await afRequest(url: url)
        let finalData = try JSONDecoder().decode(TokenSimplePriceCoingeckoUsdModel.self, from: undecodedData)
        
        return finalData
    } catch(let error) {
        print(" Error on getDataFromAPI(): ", error)
    }
    return ""
}

当我打印 return 时,我得到:

TokenSimplePriceCoingeckoUsdModel(usd: nil, usd_market_cap: nil, usd_24h_vol: nil, usd_24h_change: nil, last_updated_at: nil)

编辑:如果我这样做:

print(String(data: undecodedData, encoding: .utf8)!)let undecodedData ... 行下它打印数据,所以确认问题是在用我的模型解码它时,我做错了什么?

我从来没有直接使用 alamofire 发出网络请求,但似乎错误在于你如何解码响应,假设 undecodedData 已经包含你想要的数据,你当前的响应模型不解码“比特币”密钥,因此结构为零,您可以将结构更改为

struct BitcoinStats: Codable, Hashable {
    let bitcoin: TokenSimplePriceCoingeckoUsdModel
}

struct TokenSimplePriceCoingeckoUsdModel: Codable, Hashable {
    let usd, usd_market_cap, usd_24h_vol, usd_24h_change: Double?
    let last_updated_at: Int?
}

或者您可能想尝试直接解码“比特币”密钥的值,这样您就可以保持当前结构不变

更新: 因为 JSON 除了“比特币”之外还有其他密钥,这是我提出的动态解码数据的解决方案,无需对密钥进行硬编码: pastecode.io/s/tkim2jf0

您的值在 bitcoin 对象中,因此您也需要对其进行解码。您可以从 quicktype.io:

这个结构开始
struct Prices: Decodable {
    let bitcoin: Bitcoin
}

// MARK: - Bitcoin
struct Bitcoin: Decodable {
    let usd: Int
    let usdMarketCap, usd24HVol, usd24HChange: Double
    let lastUpdatedAt: Int

    enum CodingKeys: String, CodingKey {
        case usd
        case usdMarketCap = "usd_market_cap"
        case usd24HVol = "usd_24h_vol"
        case usd24HChange = "usd_24h_change"
        case lastUpdatedAt = "last_updated_at"
    }
}

然后就可以使用Alamofire 5.5新的async方法自动解码了:

let response = await AF.request(url).serializingDecodable(Prices.self).response