當我從coinapi.com(https://rest-sandbox.coinapi.io/v1/assets/?apikey=72869C8A-D49B-4DC5-9A3B-17D9804AEE97)轉換JSON時,我得到的問題是 "資料無法讀取,因為格式不正確"。我得到了一個問題 "資料無法被讀取,因為它的格式不正確"。
轉換后的結果是:
struct CryptListStruct。Codable {
let assetID, name: String
let typeIsCrypto: Int
let dataQuoteStart, dataQuoteEnd, dataOrderbookStart, dataOrderbookEnd: String String
let dataTradeStart, dataTradeEnd: String
let dataSymbolsCount: Int
let volume1HrsUsd, volume1DayUsd: Double
let volume1MthUsd: Int[/span].
letpriceUsd: 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"/span>
case idIcon = "id_icon"/span>
case dataStart = "data_start"
case dataEnd = "data_end" >。
}
}
我認為這是因為那里有很多資料,而且它們是不一樣的。我怎樣才能得到正確的模型呢?
這就是我的方法。
我的函式是這樣的:
。
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"/span>, header: header, completion: {
(data) in.
do {
guard let data = data else {return }
let crpytList = try JSONDecoder() 。 decode(CryptListStruct.self, from: data)
DispatchQueue.main.async {
完成(crpytList)
}
} catch let err {
error(err.localizedDescription)
}
}, error: 錯誤)
}
``
uj5u.com熱心網友回復:
首先
千萬不要print(error.localizedDescription).
。
在一個JSONDecoder catch塊中。你會得到一個通用但相當無意義的錯誤資訊。
總是列印整個錯誤,DecodingErrors是非常具有描述性的
print(error)
你的代碼包含三個主要錯誤,其中一個(錯誤#3)出現了多次
錯誤#1typeMismatch(Swift.Dictionary<Swift.String, Any> , Swift.DecodingError.Context(codingPath: [], debugDescription: "預計解碼Dictionary<String, Any> 但發現是一個陣列。", underlyingError: nil))
表示根物件是一個陣列,JSON明確以[
解決方案:解碼 [CryptListStruct].self
錯誤 #2
dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "volume_1mth_usd", intValue: nil)], debugDescription: "決議的JSON數字<3699822674922524.74>不適合Int。", underlyingError: nil))
表示收到的值3699822674922524.74實際上是一個Double。
解決方案:宣告
let volume1MthUsd: Double。
錯誤 #3
keyNotFound(CodingKeys(stringValue: "id_icon", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 4", intValue: 4)], debugDescription: "沒有與鍵CodingKeys(stringValue:"id_icon",intValue:nil)("id_icon")相關的值。", underlyingError:nil))
表明鍵id_icon在陣列的第5項中缺少(至少是)。
解決方案:將型別宣告為可選的
let idIcon : String?
同樣的錯誤發生在dataTradeStart, dataTradeEnd, dataQuoteStart, dataQuoteEnd, dataOrderbookStart, dataOrderbookEnd, dataStart, dataEnd
let dataQuoteStart, dataQuoteEnd, dataOrderbookStart, dataOrderbookEnd。String?
let dataTradeStart, dataTradeEnd : String?
let dataStart, dataEnd: String?
旁注:
如果你把assetID替換成assetId并添加convertFromSnakeCase鍵解碼策略,你可以洗掉整個CodingKeys列舉
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let crpytList = try decoder.decode([CryptListStruct].self, from: data)
uj5u.com熱心網友回復:
回應模型
typealias CryptResult = [CryptListElement]
//MARK: - CryptListElement
struct CryptListElement。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
letpriceUsd: 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"/span>
case idIcon = "id_icon"/span>
case dataStart = "data_start"
case dataEnd = "data_end" >。
}
}
解碼器代碼:
let result = try? newJSONDecoder().decode(CryptResult.self, from: jsonData)
我們需要使用CryptResult而不是CryptListElement
。uj5u.com熱心網友回復:
試試這個(注意選項,以及volume1MthUsd: Double),對我有用:
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
letpriceUsd: 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"/span>
case idIcon = "id_icon"/span>
case dataStart = "data_start"
case dataEnd = "data_end" >。
}
}
EDIT1:
這是我測驗答案的方法:
import SwiftUI
@main
struct TestApp。App {
var body。some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var cryptList = [CryptListStruct]()
var body: some View {
Text(cryptList.count > 0 ? "fetched (cryptList.count)" : "fetching..." )
.任務 {
cryptList = await fetchThem()
print("
----> cryptList: (cryptList.count) ""。
")
}
// use closure
//.onAppear {
//.getCryptList() { list in.
// cryptList = list[/span
// }
// }
}
private func fetchThem<T: Decodable>() async -> [T] {
var url = URL(string: "https://rest-sandbox.coinapi.io/v1/assets/?apikey=72869C8A-D49B-4DC5-9A3B-17D9804AEE97")!
do {
let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url))
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else{
print(URLError(.badServerResponse)
return [] 。
}
return try JSONDecoder().Decode([T].self, from: data)
}
catch {
return [] 。
}
}
}
編輯2:使用封閉式風格:
private func getCryptList(_ completion: @escaping ([CryptListStruct]) -> Void) {
URLSession.shared.dataTask(with: URL(string: "https://rest-sandbox.coinapi.io/v1/assets/?apikey=72869C8A-D49B-4DC5-9A3B-17D9804AEE97")!。
completionHandler: { data, response, error in.
guard let data = data, error = nil else {
print("error: (error?.localizedDescription as Optional))
return。
}
do {
let cryptList = try JSONDecoder() 。 decode([CryptListStruct].self, from: data)
完成(cryptList)
}
catch {
print(String(describing: error))
}
}).恢復()
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/322806.html
標籤:
