Swift中使用Alamofire调用POST API无法获取JSON响应问题
解决NetworkManager中POST请求参数无效的问题
问题概述
我在NetworkManager中实现了通用请求方法serviceCall,但该方法仅对GET请求有效,使用POST请求并携带参数时返回解析错误。
错误信息
{ "code": "-32700", "meaning": "Undefined array key \"params\"", "message": "Parse error" }
测试代码
func testServiceCall(){ let parameters = ["name": "testinggg", "job": "manager"] as [String : Any] let request = RequestObject(params: parameters, method: .post, path: "https://reqres.in/api/users", isTokenNeed: false, vc: self) WebService.sharedInstance.serviceCall(UserModel.self, with: request) { (response, error) in print("user post response \(response)") } }
NetworkManager代码
class GeneralResponse<T: Codable>: Codable { var jsonrpc: String var result: T? let error: ErrorClass? } struct ErrorClass: Codable { let code, message, meaning: String? } struct RequestObject { var params: [String: Any]? var method: HTTPMethod var path: String var isTokenNeed: Bool = false var vc: UIViewController? } class NetworkManager { private let decoder: JSONDecoder static let sharedInstance = NetworkManager() public init(_ decoder: JSONDecoder = JSONDecoder()) { self.decoder = decoder } public func serviceCall<T: Codable>(_ objectType: T.Type, with request: RequestObject, completion: @escaping (T?, Error?) -> Void) { AF.request(request.path, method: request.method, parameters: request.params,encoding: JSONEncoding.default, headers: request.isTokenNeed ? ["Authorization" : "Bearer hnjjdshjdsh", "Accept": "application/json"] : ["": ""]) .responseJSON { response in switch response.result { case .success(_): do { let data = response.data let responseData = try self.decoder.decode(T.self, from: data ?? Data()) completion(responseData, nil) } catch { completion(nil, error) print("in catch \(error.localizedDescription)") } case .failure(let AFError): let error = AFError print(error.localizedDescription) print("failure error: \(error)") } } } }
问题分析
- 参数格式不匹配:后端报错提示找不到
params键,说明它期望请求体是一个包含params字段的JSON对象,但当前代码直接把参数作为根节点发送,不符合后端的jsonrpc格式要求。 - 无效请求头:当不需要Token时,代码传入了
["": ""]作为请求头,这会生成一个无效的空键头,可能导致服务器解析异常。 - 响应解析错误:后端返回的是
GeneralResponse<T>格式的jsonrpc响应,但代码直接解析T类型,导致解析失败。
解决方案
修改后的NetworkManager核心代码
class NetworkManager { private let decoder: JSONDecoder static let sharedInstance = NetworkManager() public init(_ decoder: JSONDecoder = JSONDecoder()) { self.decoder = decoder } public func serviceCall<T: Codable>(_ objectType: T.Type, with request: RequestObject, completion: @escaping (T?, ErrorClass?) -> Void) { // 将参数包装到params字段中,符合后端jsonrpc格式要求 let parameters = request.params.map { ["params": $0] } // 修复请求头:不需要Token时传nil,避免无效空键 let headers: HTTPHeaders? = request.isTokenNeed ? [ "Authorization": "Bearer hnjjdshjdsh", "Accept": "application/json" ] : nil AF.request(request.path, method: request.method, parameters: parameters, encoding: JSONEncoding.default, headers: headers) .responseJSON { response in switch response.result { case .success(_): guard let data = response.data else { completion(nil, ErrorClass(code: "1", message: "无响应数据", meaning: "Empty response data")) return } do { // 先解析外层的GeneralResponse,再取出result数据 let generalResponse = try self.decoder.decode(GeneralResponse<T>.self, from: data) completion(generalResponse.result, generalResponse.error) } catch { completion(nil, ErrorClass(code: "\(error._code)", message: error.localizedDescription, meaning: "解析失败")) print("解析错误: \(error.localizedDescription)") } case .failure(let afError): completion(nil, ErrorClass(code: "\(afError._code)", message: afError.localizedDescription, meaning: "网络请求失败")) print("请求失败: \(afError)") } } } }
调整测试代码的回调处理
func testServiceCall(){ let parameters = ["name": "testinggg", "job": "manager"] as [String : Any] let request = RequestObject(params: parameters, method: .post, path: "https://reqres.in/api/users", isTokenNeed: false, vc: self) WebService.sharedInstance.serviceCall(UserModel.self, with: request) { (response, error) in if let error = error { print("请求错误: \(error.message ?? "未知错误")") } else { print("user post response \(response)") } } }
关键修改点说明
- 参数包装:将请求参数包裹在
params字段中,匹配后端对jsonrpc格式的要求,解决"Undefined array key 'params'"错误。 - 请求头修复:移除无效的空键请求头,改为
nil,避免服务器解析异常。 - 响应解析调整:先解析外层的
GeneralResponse<T>,再提取内部的result数据,确保和后端返回的响应格式一致。
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

