简体   繁体   English

如何使用alamofire httpstatusCode

[英]how to use alamofire httpstatusCode

I want a diffrerent responseDecodable on the httpStatusCode我想要 httpStatusCode 上的不同 responseDecodable

server return服务器返回

if statusCode == 200
resonseBody
{id: number}

if statusCode 400..<500
resonseBody
{
code: String
timestamp: String
message: String
}

so now my code is所以现在我的代码是

 AF.request(url, method: .post, headers: header).responseData { response in
            switch response.result {
            case .success(let data) :
                guard let response = response.response else {return}
                let json = try? JSONSerialization.jsonObject(with: data)
                switch response.statusCode {
                    case 200:
                    if let json = json as? [String: Any] , let message = json["id"] as? Int{print(message)}
                case (400..<500):
                    if let json = json as? [String: Any] , let message = json["message"] as? String{print(message)}
                default:
                    return
                }
            case .failure(let err) :
                print(err)
            }
        }

I try this code convert responseDecodable我试试这个代码转换 responseDecodable

struct a: Codable {var id: Int}

struct b: Codable{
    var code: String
    var timestamp: String
    var message: String
}

AF.request(url, method: .post, headers: header).responseDecodable(of: a.self) { response in
            guard let data = response.value else {return}
            print(data)
            }
            .responseDecodable(of: b.self) { response in
            guard let data = response.value else {return}
            print(data)
            }

but this way Regardless statusCode return both a and b但是这样不管 statusCode 都返回 a 和 b

I want stautsCode == 200 return a or statusCode 400..<500 return b我想要 statusCode == 200 返回 a 或 statusCode 400..<500 返回 b

What should I Do?我应该怎么办?

AFAIK, Alamofire does not have a “decode one object for success and another for failure” implementation. AFAIK,Alamofire 没有“解码一个对象成功,另一个对象失败”的实现。 You'll have to do this yourself.你必须自己做这件事。

If you really want a one distinct object for 2xx responses and another for 4xx responses, there are a few approaches:如果您真的想要一个用于 2xx 响应的不同对象和另一个用于 4xx 响应的对象,有几种方法:

  1. Use validate to handle the 2xx responses, and manually decode 4xx responses in the error handler.使用validate处理 2xx 响应,并在错误处理程序中手动解码 4xx 响应。

     AF.request(url, method: .post, parameters: parameters, headers: header) .validate(statusCode: 200 ..< 300) // only 2xx are auto-decoded for us; handle 4xx responses in `failure` handler .responseDecodable(of: Foo.self) { response in switch response.result { case .failure(let error): guard let statusCode = response.response?.statusCode, 400 ..< 500 ~= statusCode, let data = response.data, let apiError = try? JSONDecoder().decode(ApiErrorResponse.self, from: data) else { print("other error:", error) // didn't parse `ApiErrorResponse` object, so obviously some other error return } print("apiError:", apiError) // this is our parsed API error object case .success(let foo): print("success:", foo) } }
  2. If you want, you could write your own ResponseSerializer to parse 2xx and 4xx responses differently:如果需要,您可以编写自己的ResponseSerializer以不同方式解析 2xx 和 4xx 响应:

     struct ApiErrorResponse: Decodable, Error { let code: String let timestamp: String let message: String } final class ApiResponseSerializer<T: Decodable>: ResponseSerializer { lazy var decoder = JSONDecoder() private lazy var successSerializer = DecodableResponseSerializer<T>(decoder: decoder) private lazy var errorSerializer = DecodableResponseSerializer<ApiErrorResponse>(decoder: decoder) public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T { if let error = error { throw error } guard let response = response else { throw URLError(.badServerResponse) } switch response.statusCode { case 400 ..< 500: let apiErrorObject = try errorSerializer.serialize(request: request, response: response, data: data, error: nil) throw apiErrorObject default: return try successSerializer.serialize(request: request, response: response, data: data, error: nil) } } }

    And then you can do:然后你可以这样做:

     AF.request(url, method: .post, parameters: parameters, headers: header) .response(responseSerializer: ApiResponseSerializer<Foo>()) { response in switch response.result { case .failure(.responseSerializationFailed(reason: .customSerializationFailed(error: let apiErrorObject))): print("api response error:", apiErrorObject) case .failure(let error): print("some other error:", error) case .success(let foo): print("success:", foo) } }

    I find the nesting of the parsed error object to be a little tedious, but it does abstract the 2xx vs 4xx logic out of the response / responseDecoder completion handler.我发现解析错误对象的嵌套有点乏味,但它确实从response / responseDecoder完成处理程序中抽象出 2xx 与 4xx 逻辑。

In both of these, I'm considering all 2xx responses as success, not just 200. Some servers return 2xx codes other than just 200.在这两种情况下,我都认为所有 2xx 响应都是成功的,而不仅仅是 200。一些服务器返回 2xx 代码,而不仅仅是 200。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM