web-dev-qa-db-ja.com

Array <Any>をデコードする予定ですが、代わりに辞書が見つかりました

私は配列を返すAPIからデータを取得していましたが、「サブレベル」を持つAPIでそれを置き換える必要がありました。

_RAW:
    ETH:
        USD:
             TYPE:              "5"
             MARKET:            "CCCAGG"
             FROMSYMBOL:        "ETH"
             TOSYMBOL:          "USD"
             PRICE:             680.89
             CHANGEPCT24HOUR    :   -9.313816893529749
_

これが私の構造です:

_struct Ethereum: Codable {

    let percentChange24h: String
    let priceUSD: String

    private enum CodingKeys: String, CodingKey {
        case priceUSD = "PRICE", percentChange24h = "CHANGEPCT24HOUR"
    }
}
_

そして実装:

_    func fetchEthereumInfo(completion: @escaping (Ethereum?, Error?) -> Void) {
    let url = URL(string: "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD")!

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }
        do {
            if let ethereumUSD = try JSONDecoder().decode([Ethereum].self, from: data).first {
                print(ethereumUSD)
                completion(ethereumUSD, nil)
            }
        } catch {
            print(error)
        }
    }
    task.resume()
}
_

コンソールはtypeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))を出力します

自分のコードで何を更新するのか、この形式のAPIが何であるのかを本当に理解できない

5
Wizzardzz

まず、JSONには配列が含まれていません。 JSONの読み取りは非常に簡単です。コレクションタイプは2(2!)のみで、配列[]および辞書{}。ご覧のとおり、JSON文字列には角括弧がまったくありません。

すべての(サブ)辞書{}は独自のタイプにデコードする必要があるため、

struct Root : Decodable {
    private enum CodingKeys : String, CodingKey { case raw = "RAW" }
    let raw : RAW
}

struct RAW : Decodable {
    private enum CodingKeys : String, CodingKey { case eth = "ETH" }
    let eth : ETH
}

struct ETH : Decodable {
    private enum CodingKeys : String, CodingKey { case usd = "USD" }
    let usd : USD
}

struct USD : Decodable {

    private enum CodingKeys : String, CodingKey {
        case type = "TYPE"
        case market = "MARKET"
        case price = "PRICE"
        case percentChange24h = "CHANGEPCT24HOUR"
    }
    let type : String
    let market : String
    let price : Double
    let percentChange24h : Double
}

JSONをデコードして印刷するにはpercentChange24h書かなければならない

 let result = try JSONDecoder().decode(Root.self, from: data)
 print("percentChange24h", result.raw.eth.usd.percentChange24h)
16
vadian