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
相关产品推荐
相关产品推荐

