使用 Retrofit 和 execute() 从错误响应中获取正文

Get body From error response with Retrofit with execute()

所以出于某种原因,我需要像这样执行我的调用:

val result = manager.call.execute()
if (result.isSuccess) {
   //do stuff
} else {
    //handle exeption
}

当我的代码到达 else 括号时 result.body() 为空并且 result.errorBody() 的缓冲区内容为 0 但不是其长度。

但是,这是我从改造中得到的日志:

<-- 400 Bad Request https://cubus-friends-
...
D/OkHttp: {"error":"validation_error","error_description":"No user with that phone number"}
D/OkHttp: <-- END HTTP (81-byte body)  

如何将 json 错误字符串放入代码中的 else 括号中?

根据@florian-do 的建议,Getting JSON from RetrofitError 包含答案,请参阅答案末尾的 Retrofit2 部分。但是,我使用的是 kotlin,这个小改动是获得转换器所必需的:

val a = object : Annotation{}
val converter = Backend.retrofit. //this is for accessing my Retrofit object
        responseBodyConverter<Error>(Error::class.java, arrayOf(a))

您可以像这样创建一个简单的 class

class ApiError constructor(error: Throwable) {
    var errorMessage = "An error occurred"
    var error = "error"

    init {
        if (error is HttpException) {
            val errorJsonString = error.response()
                                       .errorBody()?.string()
            parsedString = JsonParser().parse(errorJsonString)
            this.error = parsedString.asJsonObject["error"].asString
            this.errorMessage = parsedString.asJsonObject["error_message"].asString
        } else {
            this.errorMessage = error.message ?: this.errorMessage
        }
    }
}

然后像这样使用它

try  { 
    val result = manager.call.execute()
} catch(error: IOException) {
    ApiError(error).errorMessage
}

这种方法的优点是您可以在代码中的任何地方使用 ApiError(error).errorMessage,而无需重写解析逻辑。

全部来自this blog post(我写的)。

如果您想在错误响应到来时获取数据(通常是 200 以外的响应代码),您可以在 onResponse() 方法中这样做:

  if (result.isSuccess) {
  //do stuff
  } else {
  //handle exeption
      val converter = 
      ApiClient.getClient()?.responseBodyConverter<ErrorResponseData>(
                ErrorResponseData::class.java, arrayOfNulls<Annotation>(0))
                        var errorResponse: ErrorResponseData? = null
                            errorResponse = converter?.convert(response.errorBody())
                            if (errorResponse != null) {
                                //TODO: Handle Error case...
                            }
  }

这是不创建未使用的注释对象实例的最佳方法

responseBodyConverter<Error>(Error::class.java, arrayOfNulls<Annotation>(0))