You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift/SwiftUI解码JSON报错:期望解码[String:CurrencyData]字典但实际为数组

问题解决方案

错误原因

"Expected to decode Dictionary<String, CurrencyData> but found an array instead."
该错误由解码类型和接口实际返回的JSON结构不匹配导致:

  • 你定义的Currency类型为[String: CurrencyData],是键值对字典结构
  • 你请求的目标接口返回的JSON根节点是数组,每个数组元素才是符合CurrencyData结构的对象

修改步骤

  1. 修改Currency类型别名定义,将字典类型改为数组类型
  2. 修改接口请求成功后的遍历逻辑,数组元素直接是CurrencyData实例,不需要再取.value属性
  3. 优化主线程调度逻辑,避免循环内多次触发主线程操作,减少性能开销

修改后完整代码

数据结构定义

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:54:00