【发布时间】: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)