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

Swift解析JSON类型不匹配求助:数组与字典解码冲突

问题解决:JSON解码类型不匹配与赋值错误

错误根源分析

  • 第一个解码错误:你的API返回的是单个JSON对象(字典结构),但你尝试用[Game].self解码成数组,解码器预期数组却拿到字典,因此抛出typeMismatch错误。
  • 第二个赋值错误:改成解码单个Game对象后,你试图把单个Game实例赋值给类型为[Game]的games变量,类型不匹配导致报错。

解决方案1:修改ViewModel为存储单个Game对象(适合API仅返回单条数据场景)

如果API每次只返回一个Game数据,直接把ViewModel里的数组属性改成可选的单个Game对象:

import Foundation

struct Game: Hashable, Codable {
    let question: String
    let solution: Int
}

class ViewModel: ObservableObject {
    // 将数组改为可选的单个Game对象
    @Published var game: Game? = nil
    
    func fetch() {
        guard let url = URL(string: "https://marcconrad.com/uob/smile/api.php") else {
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let data = data, error == nil else {
                return
            }
            
            do {
                // 解码单个Game对象
                let game = try JSONDecoder().decode(Game.self, from: data)
                DispatchQueue.main.async {
                    self?.game = game
                    print(game)
                }
            }
            catch {
                print(error)
            }
        }
        task.resume()
    }
}

解决方案2:保持数组属性,将单个对象包装成数组赋值(适合后续可能扩展为多条数据的场景)

如果需要保留[Game]类型的games属性,解码单个对象后用数组包裹再赋值:

import Foundation

struct Game: Hashable, Codable {
    let question: String
    let solution: Int
}

class ViewModel: ObservableObject {
    @Published var games: [Game] = []
    
    func fetch() {
        guard let url = URL(string: "https://marcconrad.com/uob/smile/api.php") else {
            return
        }
        
        let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let data = data, error == nil else {
                return
            }
            
            do {
                // 解码单个Game对象
                let game = try JSONDecoder().decode(Game.self, from: data)
                DispatchQueue.main.async {
                    // 将单个对象包装成数组后赋值
                    self?.games = [game]
                    print(self?.games ?? [])
                }
            }
            catch {
                print(error)
            }
        }
        task.resume()
    }
}

内容的提问来源于stack exchange,提问作者Kieron Joy-Kimber

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:25:36