将CoinAPI返回的JSON转换为Swift模型时遭遇格式错误的解决方案咨询
解决CoinAPI JSON转Swift模型的格式错误问题
首先,咱们先揪出最直接的错误:你请求的CoinAPI /v1/assets 接口返回的是一个数组(一堆加密资产对象的集合),但你现在的代码是尝试把它解码成单个CryptListStruct对象,这肯定会报错说格式不对,这是核心问题之一。
接下来,再看你的模型结构体,还有几个字段类型和可选性的问题——毕竟API返回的数据里有些字段可能不是所有条目都有,或者类型和你定义的不一致:
1. 修正解码对象为数组
先改请求函数里的解码逻辑,把单个对象解码改成数组解码,同时调整completion的参数类型对应数组:
func getCryptList(_ completion: @escaping ([CryptListStruct]) -> Void, _ error: @escaping (String) -> Void){ let header: [String: String] = [:] self.get(url: "https://rest.coinapi.io/v1/assets/?apikey=367FB27A-371B-4DBD-AB81-E98AAFE857B2", header: header, completion: { (data) in do { guard let data = data else { error("No data received") return } let cryptList = try JSONDecoder().decode([CryptListStruct].self, from: data) DispatchQueue.main.async { completion(cryptList) } } catch let err { error(err.localizedDescription) } }, error: error) }
2. 修正模型结构体的字段问题
仔细核对API返回的字段,有几个关键调整:
volume1MthUsd:API返回的是带小数的数值(比如12345.67),你定义成Int会解码失败,改成Double?更合适- 多数日期字段(比如
dataQuoteStart、dataOrderbookStart等)可能在部分资产条目中缺失,要改成可选类型 idIcon、dataSymbolsCount这类字段也可能存在空值,同样设为可选
修改后的完整模型:
struct CryptListStruct: Codable { let assetID, name: String let typeIsCrypto: Int let dataQuoteStart, dataQuoteEnd, dataOrderbookStart, dataOrderbookEnd: String? let dataTradeStart, dataTradeEnd: String? let dataSymbolsCount: Int? let volume1HrsUsd, volume1DayUsd, volume1MthUsd: Double? let priceUsd: Double? let idIcon, dataStart, dataEnd: String? enum CodingKeys: String, CodingKey { case assetID = "asset_id" case name case typeIsCrypto = "type_is_crypto" case dataQuoteStart = "data_quote_start" case dataQuoteEnd = "data_quote_end" case dataOrderbookStart = "data_orderbook_start" case dataOrderbookEnd = "data_orderbook_end" case dataTradeStart = "data_trade_start" case dataTradeEnd = "data_trade_end" case dataSymbolsCount = "data_symbols_count" case volume1HrsUsd = "volume_1hrs_usd" case volume1DayUsd = "volume_1day_usd" case volume1MthUsd = "volume_1mth_usd" case priceUsd = "price_usd" case idIcon = "id_icon" case dataStart = "data_start" case dataEnd = "data_end" } }
3. 额外小技巧:兼容API字段变动
如果API后续新增了未定义的字段,默认的JSONDecoder会因为遇到未知键而解码失败。你可以给解码器添加配置,忽略未知键:
let decoder = JSONDecoder() decoder.unknownKeysEncodingStrategy = .discard // 忽略模型中未定义的键 let cryptList = try decoder.decode([CryptListStruct].self, from: data)
这样即使API返回了新字段,解码也不会失败,灵活性更高。
内容的提问来源于stack exchange,提问作者Nurjan Ababakirov
相关产品推荐
相关产品推荐

