iOS开发:如何用Alamofire解析JSON Codable数组
如何用Alamofire解析JSON数组的Codable数据
核心问题分析
你的解析失败主要源于以下几个不匹配:
- API返回的是直接的Order对象数组,但你试图用
OrderList结构体去解析,结构不匹配 Order的CodingKeys使用了大写的Name/Email等键,但API返回的是小写的name/email,键名不匹配coffeeSize枚举定义的CodingKeys是映射s/m/l,但API返回的是完整的small/medium/large,枚举解析逻辑错误- 解析代码绕了弯路,没必要先转成JSON再序列化数据,Alamofire原生支持直接解析Codable
修正步骤及代码
1. 修正模型结构
去掉多余的OrderList,直接用[Order]接收数组;修正CodingKeys匹配API返回的键名;修正coffeeSize的解析逻辑;去掉不必要的隐式解包:
// 咖啡类型枚举,rawValue匹配API返回的字符串 enum CoffeeType: String, Codable { case cappuccino = "Cappuccino" case lattee = "Lattee" case espressino = "Espressino" case cortado = "Cortado" } // 咖啡尺寸枚举,直接匹配API返回的字符串,无需自定义CodingKeys enum CoffeeSize: String, Codable { case small, medium, large } struct Order: Codable { let email: String let name: String let size: CoffeeSize let type: CoffeeType // 键名完全匹配API返回的小写字段 enum CodingKeys: String, CodingKey { case name, email, type, size } // 自定义初始化处理可选值与默认值 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) email = try container.decodeIfPresent(String.self, forKey: .email) ?? "" name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Guest" size = try container.decodeIfPresent(CoffeeSize.self, forKey: .size) ?? .small type = try container.decodeIfPresent(CoffeeType.self, forKey: .type) ?? .lattee } } struct Resource<T: Codable> { let url: URL var httpMethod: HTTPMethod = .get }
2. 简化Alamofire解析代码
使用Alamofire原生的responseCodable方法直接解析,避免手动转换的错误:
func load<T>(resource: Resource<T>, completion: @escaping (Result<T, Error>) -> Void) { AF.request(resource.url, method: resource.httpMethod) .validate() // 验证HTTP状态码合法性 .responseCodable(decoder: JSONDecoder()) { (response: DataResponse<T, AFError>) in switch response.result { case .success(let data): print(data) completion(.success(data)) case .failure(let error): print(error.localizedDescription) completion(.failure(error)) } } }
3. 调用示例
调用时指定泛型为[Order].self,匹配API返回的数组结构:
guard let myurl = URL(string: "你的API地址") else { return } let resource = Resource<[Order]>(url: myurl) load(resource: resource) { result in switch result { case .success(let orders): // 处理获取到的订单数组 for order in orders { print("姓名:\(order.name),邮箱:\(order.email),咖啡类型:\(order.type.rawValue),尺寸:\(order.size.rawValue)") } case .failure(let error): // 处理错误 print("解析失败:\(error)") } }
关键要点总结
- 模型结构必须与API返回的JSON结构完全匹配:数组对应
[Model],对象对应单个Model CodingKeys的键名需与JSON中的键完全一致(大小写敏感)- 枚举的
rawValue要和JSON中的字符串值完全匹配,无需多余的CodingKeys除非需要映射不同键名 - 优先使用Alamofire的
responseCodable方法,简化流程减少错误 - 避免使用隐式解包可选类型(
!),改用默认值或普通可选类型保证代码安全
内容的提问来源于stack exchange,提问作者sweetSwift
相关产品推荐
相关产品推荐

