如何使用Alamofire 5解析JSON数组?
Alamofire 5 JSON数组解码失败求助
问题概述
使用Alamofire 5解析JSON数组时持续失败,尝试过responseString、responseData、responseJSON及responseDecodable搭配Codable模型等多种方式,均无法正常解析。错误提示显示"期望解码Array
返回的JSON示例
[ { "Date": "2022-08-08T00:00:00", "Day": "Fri", "AbsenceCount": 0, "AbsenceRequestComments": "Request permitted", "Color": "No", "IsRequestPermitted": true }, { "Date": "2022-09-09T00:00:00", "Day": "Sat", "AbsenceCount": 0, "AbsenceRequestComments": "Request permitted", "Color": "No", "IsRequestPermitted": true }, { "Date": "2022-12-15T00:00:00", "Day": "Sun", "AbsenceCount": 0, "AbsenceRequestComments": "Request permitted", "Color": "No", "IsRequestPermitted": true } ]
请求代码
let request = AF.request(requestURL, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: returnHeader()) .validate() .responseDecodable(of: [CoverCheckForDay].self) { response in switch response.result { case .success: guard let value = response.value else { failure(""); return } success(value) case .failure(let error): failure(error.localizedDescription) } }
Codable模型定义
struct CoverCheckForDay: Codable { let date: String let day: String let absenceCount: Int let absenceRequestComments: String let color: String let isRequestPermitted: Bool enum CodingKeys: String, CodingKey { case date = "Date" case day = "Day" case absenceCount = "AbsenceCount" case absenceRequestComments = "AbsenceRequestComments" case color = "Color" case isRequestPermitted = "IsRequestPermitted" } }
错误信息
▿ Optional<AFError> ▿ some : AFError ▿ responseSerializationFailed : 1 element ▿ reason : ResponseSerializationFailureReason ▿ decodingFailed : 1 element ▿ error : DecodingError ▿ typeMismatch : 2 elements - .0 : Swift.Array<Any> ▿ .1 : Context - codingPath : 0 elements - debugDescription : "Expected to decode Array<Any> but found a string/data instead." - underlyingError : nil
请求参数
▿ 3 elements ▿ 0 : 2 elements - key : "employeeId" - value : 13558 ▿ 1 : 2 elements - key : "dates" ▿ value : 3 elements ▿ 0 : CoverRequestArray ▿ date : Optional<String> - some : "01/09/2022" ▿ day : Optional<String> - some : "Thu" ▿ 1 : CoverRequestArray ▿ date : Optional<String> - some : "02/09/2022" ▿ day : Optional<String> - some : "Fri" ▿ 2 : CoverRequestArray ▿ date : Optional<String> - some : "03/09/2022" ▿ day : Optional<String> - some : "Sat" ▿ 2 : 2 elements - key : "siteId" - value : 440
排查与解决步骤
1. 确认服务器实际返回内容
服务器可能返回了转义后的字符串形式JSON(而非直接的JSON数组),先用responseData打印原始响应:
AF.request(requestURL, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: returnHeader()) .validate() .responseData { response in switch response.result { case .success(let data): if let rawStr = String(data: data, encoding: .utf8) { print("原始响应:\(rawStr)") } case .failure(let error): print(error) } }
如果打印结果带\"转义符,说明需要先将字符串转成Data再解码:
// 在responseData的success分支内处理 if let rawStr = String(data: data, encoding: .utf8), let fixedData = rawStr.data(using: .utf8) { do { let decodedResult = try JSONDecoder().decode([CoverCheckForDay].self, from: fixedData) success(decodedResult) } catch { failure(error.localizedDescription) } }
2. 调整请求参数编码
当前使用URLEncoding.default,但服务器对数组参数的编码规则可能不匹配。尝试自定义数组编码方式:
// 可选编码方式:.brackets 生成 dates[]=xxx,.noBrackets 生成 dates=xxx let customEncoding = URLEncoding(arrayEncoding: .brackets) AF.request(requestURL, method: .get, parameters: parameters, encoding: customEncoding, headers: returnHeader())
3. 增强模型兼容性
临时将模型属性改为可选类型,排查是否存在字段为null导致的解码失败:
struct CoverCheckForDay: Codable { let date: String? let day: String? let absenceCount: Int? let absenceRequestComments: String? let color: String? let isRequestPermitted: Bool? enum CodingKeys: String, CodingKey { case date = "Date" case day = "Day" case absenceCount = "AbsenceCount" case absenceRequestComments = "AbsenceRequestComments" case color = "Color" case isRequestPermitted = "IsRequestPermitted" } }
若解码成功,再逐个将可选属性改回非可选,定位问题字段。
内容的提问来源于stack exchange,提问作者Arsienij
相关产品推荐
相关产品推荐

