使用Swift JSONDecoder解码JSON失败,报类型不匹配错误求助
这个报错的原因很明确——你试图直接解码一个[Audiobook]数组,但实际返回的JSON根结构是字典,里面的data字段才是你需要的Audiobook数组。你的代码里其实已经定义了对应的结构体(那个叫Data的结构体),但解码的时候根本没用到它,这就是问题所在。
下面是具体的修复步骤:
1. 修复结构体命名(避免冲突)
你定义的Data结构体和Foundation框架自带的Data类型重名了,这很容易导致编译混淆,先把它改成更有语义的名字,比如AudiobookResponse:
import Foundation struct AudiobookResponse: Decodable { let data: [Audiobook] } struct Audiobook: Decodable { let id: Int? let descricao: String? let urlImagem: String? }
2. 修改解码逻辑
原来的代码直接尝试解码数组,现在要改成解码AudiobookResponse这个根结构体,然后从中取出data数组。同时还要修正completion的返回值——你之前错误地传了nil,这会导致调用方永远拿不到解析后的数据:
import Foundation struct APIClient { static func getAudiobooksAPI(completion: @escaping ([Audiobook]?) -> Void) { let url = URL(string: "https://alodjinha.herokuapp.com/categoria") let session = URLSession.shared guard let unwrappedURL = url else { print("Error unwrapping URL") completion(nil) return } let dataTask = session.dataTask(with: unwrappedURL) { (data, response, error) in guard let unwrappedData = data else { print("Error unwrapping data") completion(nil) return } do { // 先解码根结构体 let apiResponse = try JSONDecoder().decode(AudiobookResponse.self, from: unwrappedData) print(apiResponse.data) // 把解析后的数组传给回调 completion(apiResponse.data) } catch { print("Could not get API data. \(error), \(error.localizedDescription)") completion(nil) } } dataTask.resume() } }
额外的小优化
我还在guard语句里补充了completion(nil),这样无论哪个步骤失败(比如URL无效、数据为空),都能及时通知调用方,避免出现回调不执行的情况。
这样修改后,你的解码逻辑就能和JSON结构匹配,程序也就不会崩溃了。
内容的提问来源于stack exchange,提问作者Bruno Vavretchek
相关产品推荐
相关产品推荐

