Alamofire请求出现responseSerializationFailed解码错误的技术问询
问题背景
使用Alamofire调用接口https://new.demozab.com/armup/api/public/api/post-trade时,收到解码失败错误:
failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "message", intValue: nil)], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil)))))
请求代码
func postAd(cryptoo: String, fiatt: String,locationn: String,countryy: String,marginn: String, pricee: String,minlimitt: String,maxlimitt: String,paymrntwindoww: String,paymrntmethodd: String, accountdetailss: String,infoo: String,termss: String ){ let endpoint = "https://new.demozab.com/armup/api/public/api/post-trade" let params = [ "crypto_currency_id":"1", "trade_type": "buy", "location": "", "country": "1", "market":"15", "margin":"1", "trade_price":"1", "min_transaction_limit":"1", "max_transaction_limit":"1", "payment_method":"1", "payment_window":"1", "account_details": "1", "additional_information":"1", "sunday_start":"", "sunday_end":"", "monday_start":"", "monday_end":"", "tuesday_start":"", "tuesday_end":"", "wednesday_start":"", "wednesday_end":"", "thursday_start":"", "thursday_end":"", "friday_start":"", "friday_end": "", "saturday_start": "", "saturday_end": "", "terms":"i", ] guard let url = URL(string: endpoint) else { print("Invalid URL") return } let headers: HTTPHeaders = [ "Authorization": "Bearer TVfXc1gPZbLfruJ53Q7PkkSDjSXi6gXGWXkCXg6j", "Content-Type": "application/json" ] AF.request( url, method: .post, parameters: params, headers: headers ).responseDecodable(of: CommonData.self) { (response) in print(response.result) } }
提供的API成功响应
{ "success": true, "message": "Advertisement Posted Successfully!" }
现有Model类
import Foundation // MARK: - CommonData struct CommonData: Codable { let success: Bool let message: String }
问题原因
虽然你提供的成功响应中message是字符串,但错误提示明确表明:接口在某些异常场景(比如参数校验失败、权限问题等)下,返回的message字段是字典类型,而你的CommonData模型仅将message定义为String,导致JSON解码时类型不匹配。
解决方案
方案1:修改Model支持多类型的message
使用枚举来兼容String和Dictionary两种类型的message,确保所有场景都能正常解码:
import Foundation // MARK: - CommonData struct CommonData: Codable { let success: Bool let message: MessageType } enum MessageType: Codable { case string(String) case dictionary([String: Any]) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // 先尝试解码为String if let stringValue = try? container.decode(String.self) { self = .string(stringValue) } // 再尝试解码为字典 else if let dictValue = try? container.decode([String: Any].self) { self = .dictionary(dictValue) } // 都不符合则抛出错误 else { throw DecodingError.typeMismatch(MessageType.self, DecodingError.Context( codingPath: decoder.codingPath, debugDescription: "Expected String or Dictionary type for 'message'" )) } } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .string(let value): try container.encode(value) case .dictionary(let value): try container.encode(value) } } }
方案2:手动解析JSON响应
如果不想修改Model,可以直接解析JSON对象,手动处理message字段:
AF.request(url, method: .post, parameters: params, headers: headers).responseJSON { response in switch response.result { case .success(let json): guard let responseDict = json as? [String: Any] else { print("Invalid response format") return } let success = responseDict["success"] as? Bool ?? false var messageContent = "" // 处理message字段的两种可能类型 if let msgString = responseDict["message"] as? String { messageContent = msgString } else if let msgDict = responseDict["message"] as? [String: String] { // 取字典中的第一个值,或根据业务需求处理 messageContent = msgDict.values.first ?? "Unknown error" } // 后续业务逻辑处理 print("Success: \(success), Message: \(messageContent)") case .failure(let error): print("Request failed: \(error.localizedDescription)") } }
额外排查建议
- 用Postman或类似工具,传入相同请求参数,测试错误场景下的接口响应,确认
message字段的实际结构 - 检查请求参数是否符合接口要求,比如
location为空、terms值为"i"是否符合规范,参数错误可能是导致接口返回异常格式响应的原因
内容的提问来源于stack exchange,提问作者mohammed ibrahim

