Swift/SwiftUI解码JSON报错:期望解码[String:CurrencyData]字典但实际为数组
问题解决方案
错误原因
"Expected to decode Dictionary<String, CurrencyData> but found an array instead."
该错误由解码类型和接口实际返回的JSON结构不匹配导致:
- 你定义的
Currency类型为[String: CurrencyData],是键值对字典结构 - 你请求的目标接口返回的JSON根节点是数组,每个数组元素才是符合
CurrencyData结构的对象
修改步骤
- 修改
Currency类型别名定义,将字典类型改为数组类型 - 修改接口请求成功后的遍历逻辑,数组元素直接是
CurrencyData实例,不需要再取.value属性 - 优化主线程调度逻辑,避免循环内多次触发主线程操作,减少性能开销
修改后完整代码
数据结构定义
import Foundation import SwiftUI struct CurrencyData: Codable { let r030: Int let txt: String let rate: Double let cc: String let exchangedate: String } // 替换原有字典类型定义,改为数组类型 typealias Currency = [CurrencyData]
API类实现
import SwiftUI class API: ObservableObject { @Published var currencyCode: [String] = [] @Published var priceRate: [Double] = [] @Published var exchangeDate: [String] = [] init() { fetchdata { result in switch result { case .success(let currency): // 先在后台线程处理完数据,再统一更新到主线程 let codes = currency.map(\.cc) let rates = currency.map(\.rate) let dates = currency.map(\.exchangedate) DispatchQueue.main.async { self.currencyCode = codes self.priceRate = rates self.exchangeDate = dates } case .failure(let error): print("Unable to fetch the currencies data", error) } } } func fetchdata(completion: @escaping (Result<Currency,Error>) -> ()) { guard let url = URL(string: "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json") else { return } URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { completion(.failure(error)) return } guard let safeData = data else { return } do { // 解码类型为数组,和接口返回结构匹配 let currency = try JSONDecoder().decode(Currency.self, from: safeData) completion(.success(currency)) } catch { completion(.failure(error)) } } .resume() } }
内容的提问来源于stack exchange,提问作者user17298288
相关产品推荐
相关产品推荐

