Swift使用Alamofire解析JSON时的序列化错误与属性访问问题
解决JSON序列化错误的问题
嘿,我帮你排查一下这个序列化的问题,咱们先从错误提示入手:
Error serialization: typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
这个错误很明确:你告诉JSONDecoder要解码一个数组([Description].self),但返回的JSON根结构是一个字典(外层是{"data": [...]}),这就导致了类型不匹配。接下来咱们一步步修正代码:
1. 修正结构体定义(遵循Swift规范+匹配JSON结构)
首先,Swift中类型名要首字母大写,而且你的data结构体和Foundation的Data类型重名了,建议改成更有意义的名字,比如Category。另外,你的Description结构体里的_data属性和JSON里的data键不匹配,需要调整:
import Foundation import Alamofire // 根结构体,对应JSON外层的字典 struct ApiResponse: Decodable { let data: [Category] // 和JSON里的"data"键直接对应 } // 对应数组里的每个分类元素 struct Category: Decodable { let id: Int? let descricao: String? let urlImagem: String? }
如果坚持要用_data作为属性名,也可以通过CodingKeys来做键名映射:
struct ApiResponse: Decodable { let _data: [Category] enum CodingKeys: String, CodingKey { case _data = "data" } }
2. 修正解码逻辑
因为JSON根是单个字典,所以要解码成ApiResponse.self,而不是数组类型:
func callApi() { guard let url = URL(string: "https://alodjinha.herokuapp.com/categoria") else { return } Alamofire.request(url).responseData { response in // 用responseData更直接,避免额外转换 guard let data = response.data else { return } do { let parsedResponse = try JSONDecoder().decode(ApiResponse.self, from: data) // 现在可以访问所有数据了,比如遍历打印每个分类 for category in parsedResponse.data { print("ID: \(category.id ?? 0), 描述: \(category.descricao ?? "无"), 图片URL: \(category.urlImagem ?? "无")") } // 或者单独访问某个元素的属性 if let firstCategory = parsedResponse.data.first { print(firstCategory.id) } } catch { print("序列化错误: \(error.localizedDescription)") } } }
关键修正点总结
- 类型匹配:JSON根是字典结构,所以要解码成单个结构体实例,而非数组
- 属性名匹配:确保结构体的属性名和JSON的键完全一致,或者用
CodingKeys做映射 - 命名规范:Swift类型首字母大写,避免和系统内置类型(比如
Data)重名
这样修改后,你就能正常访问data数组里的所有属性啦!
内容的提问来源于stack exchange,提问作者Bruno Vavretchek
相关产品推荐
相关产品推荐

