简体   繁体   English

Alamofire responseDecodable for model 用于响应和错误

[英]Alamofire responseDecodable for model for response and error

I'm using Alamofire to make API calls from mobile app.我正在使用 Alamofire 从移动应用拨打 API 电话。 I have struct which is map from Alamofire API calls this way我的结构是 map 来自 Alamofire API 以这种方式调用

APIManager.shared.session.request(UserRouter.signUp(username, password)).responseDecodable (of: User.self) { response in
  complition(response.value, response.error)
}

When API call is failed and returned API error is JSON format I'm getting AFError当 API 调用失败并返回 API 错误是 JSON 格式我得到AFError

▿ Optional<AFError>
  ▿ some : AFError
    ▿ responseSerializationFailed : 1 element
      ▿ reason : ResponseSerializationFailureReason
        ▿ decodingFailed : 1 element
          ▿ error : DecodingError
            ▿ keyNotFound : 2 elements
              - .0 : ContainerKeys(stringValue: "user", intValue: nil)
              ▿ .1 : Context
                - codingPath : 0 elements
                - debugDescription : "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key ContainerKeys(stringValue: \"user\", intValue: nil) (\"user\")"
                - underlyingError : nil

This is what API returning back on that call这是 API 返回的那个电话

{
  "success": false,
  "errors": [
    "Email can't be blank",
    "Password can't be blank"
  ]
}

I end up writing this to get it handle:我最终写了这个来处理它:

struct APIError: Error, Decodable {
    var success: Bool
    var errors: [String]
}
    APIManager.shared.session.request(UserRouter.signUp(username, password)).responseDecodable (of: User.self) { response in
        switch response.result {
        case .success(let value):
            complition(value, nil)
        case .failure:
            let somethingWrong = APIError(success: false, errors: ["Something went wrong. Please try again."])

            guard let data = response.data else {
                complition(nil, somethingWrong)
                return
            }
            
            do {
                let error = try JSONDecoder().decode(APIError.self, from: data)
                complition(nil, error)
            } catch {
                complition(nil, somethingWrong)
            }

        }
    }

How this code can be written better way, maybe Alamofire does support map error model as well.如何更好地编写这段代码,也许 Alamofire 也支持 map 错误 model。

A typical solution here is to use an enum as your base response type.这里的典型解决方案是使用枚举作为基本响应类型。

enum APIResult<Success: Decodable> {
  case success(Success)
  case failure(APIError)
}

You can then either make the enum directly conform to Decodable (there are many solutions out there for that), or create your own Alamofire ResponseSerializer which handles the decoding logic for you.然后,您可以使枚举直接符合Decodable (为此有很多解决方案),或者创建您自己的 Alamofire ResponseSerializer来为您处理解码逻辑。 That approach is more work but is more flexible, as you can consider the request and response when parsing.这种方法工作量更大,但更灵活,因为您可以在解析时考虑请求和响应。

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

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