【问题标题】:Swift Decoding nested JSON快速解码嵌套 JSON
【发布时间】:2018-06-20 21:07:52
【问题描述】:

我在解析来自 NBP api "http://api.nbp.pl/api/exchangerates/tables/a/?format=json" 的数据时遇到问题。我创建了 struct CurrencyDataStore 和 Currency

struct CurrencyDataStore: Codable {
var table: String
var no : String
var rates: [Currency]

enum CodingKeys: String, CodingKey {
    case table
    case no
    case rates
}

init(from decoder: Decoder) throws {

    let values = try decoder.container(keyedBy: CodingKeys.self)

    table = ((try values.decodeIfPresent(String.self, forKey: .table)))!
    no = (try values.decodeIfPresent(String.self, forKey: .no))!
    rates = (try values.decodeIfPresent([Currency].self, forKey: .rates))!
} }

struct Currency: Codable {
var currency: String
var code: String
var mid: Double

enum CodingKeys: String, CodingKey {
    case currency
    case code
    case mid
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)

    currency = try values.decode(String.self, forKey: .currency)
    code = try values.decode(String.self, forKey: .code)
    mid = try values.decode(Double.self, forKey: .mid) 
}
}

在 controllerView 类中,我编写了 2 个从 API 解析数据的方法

func getLatestRates(){
    guard let currencyUrl = URL(string: nbpApiUrl) else {
        return
    }

    let request = URLRequest(url: currencyUrl)
    let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) -> Void in

        if let error = error {
            print(error)
            return
        }

        if let data = data {
            self.currencies = self.parseJsonData(data: data)
        }
    })

    task.resume()
}

func parseJsonData(data: Data) -> [Currency] {

    let decoder = JSONDecoder()

    do{
        let currencies = try decoder.decode([String:CurrencyDataStore].self, from: data)

    }
    catch {
        print(error)
    }
    return currencies
}

此代码无效。我有这个错误“typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription:"Expected to decode Dictionary but found a array instead.",underlyingError: nil))"。

你能帮帮我吗?

【问题讨论】:

  • 您的 JSON 是顶级的 Array。所以至少decode([String:CurrencyDataStore].self,应该是decode([CurrencyDataStore].self,
  • 您的代码比应有的更冗长。试试quicktype.io 给你一个更干净的版本。如果您决定保留当前代码,解码调用应为:let currencies = try decoder.decode([CurrencyDataStore].self, from: data)

标签: json swift decode codable


【解决方案1】:

该 API 返回的 JSON 为您提供了一个数组,而不是字典,但您告诉 JSONDecoder 需要一个字典类型。将该行更改为:

let currencies = try decoder.decode([CurrencyDataStore].self, from: data)

【讨论】:

  • 谢谢。但我有 1 个元素数组。我不知道如何将此数组解析为货币数组?
  • 我有这个数组 [ConfApp.CurrencyDataStore(table: "A", no: "119/A/NBP/2018", rates: [ConfApp.Currency(currency: "bat (Tajlandia )", 代码: "THB", mid: 0.114), ConfApp.Currency(货币: "dolar amerykański", 代码: "USD", mid: 3.7606999999999999), ConfApp.Currency(货币: "dolar australijski", 代码: "澳元”,中间价:2.766)])]
  • 是的,API 的配置似乎有点奇怪。您想要的是 CurrencyDataStore 对象,因此您可以执行let dataStore = currenties[0] 之类的操作,然后 dataStore.rates 就是您想要的实际货币数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 2023-03-20
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
相关资源
最近更新 更多