简体   繁体   English

改造 2 - 当响应状态为 422(不可处理的实体)时,响应体为 null

[英]Retrofit 2 - Response body null when response status is 422 (unprocessable entity)

I'm using Retrofit to make a POST Request in my web server.我正在使用 Retrofit 在我的 Web 服务器中发出 POST 请求。

However, I can't seem to get the response body when the response status is 422 (unprocessable entity) .但是,当响应状态为422 (unprocessable entity)时,我似乎无法获取响应正文。 The response body is always null .响应正文始终为null

I want to know if I'm doing something wrong or if there's a workaround for this.我想知道我是否做错了什么,或者是否有解决方法。 Because I'm using the same json in the request with Postman , and it returns the body normally.因为我在Postman的请求中使用了相同的 json,它正常返回正文。

This is the method:这是方法:

@Headers("Content-Type: application/vnd.api+json")
@POST("my_endpoint")
Call<JsonObject> postEntry(@Header("Authorization") String authorization, @Body JsonObject json);

The body is a JsonObject, I'm not serializing like the documentation say.主体是一个 JsonObject,我没有像文档所说的那样进行序列化。 But I don't think this is the problem.但我不认为这是问题所在。

By default, when your server is returning an error code response.body() is always null .默认情况下,当您的服务器返回错误代码response.body()始终为null What you are looking for is response.errorBody() .您正在寻找的是response.errorBody() A common approach would be something like this:一种常见的方法是这样的:

    @Override
    public void onResponse(Response<JsonObject> response, Retrofit retrofit) {
        if (response.isSuccess()) {
            response.body(); // do something with this
        } else {
            response.errorBody(); // do something with that
        }
    }

If you need something advanced take a look at Interceptors and how to use them如果你需要一些高级的东西,看看拦截器如何使用它们

I got the same error.我得到了同样的错误。 My API was working using POSTMAN request but not working from Android retrofit call.我的 API 使用 POSTMAN 请求工作,但无法通过 Android 改造调用工作。

At first I was trying using @Field but it was getting error but later I've tried with @Body and it worked.起初我尝试使用 @Field 但它出错了,但后来我尝试使用 @Body 并且它起作用了。

Sample Retrofit interface call示例 Retrofit 接口调用

@POST("api/v1/app/instance")
Call<InstanceResponse> updateTokenValue(
        @HeaderMap Map<String, String> headers,
        @Body String body); 

and API calling code is:和API调用代码是:

 Map<String, String> headerMap=new HashMap<>();
        headerMap.put("Accept", "application/json");
        headerMap.put("Content-Type", "application/json");
        headerMap.put("X-Authorization","access_token");

        Map<String, String> fields = new HashMap<>();
        fields.put("app_name", "video");
        fields.put("app_version", "2.0.0");
        fields.put("firebase_token", "token");
        fields.put("primary", "1");

        ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
        Call<InstanceResponse> call = apiInterface.updateTokenValue(
                headerMap,new Gson().toJson(fields));

Well in this case you'll have to convert the response.那么在这种情况下,您必须转换响应。 Have a look at this link看看这个链接

All the steps are already provided in the link above.所有步骤都已在上面的链接中提供。

For Kotlin users here is the code solution.对于 Kotlin 用户,这里是代码解决方案。

ErrorResponse.kt (This obviously depends on your error response) ErrorResponse.kt (这显然取决于您的错误响应)

import com.squareup.moshi.Json

data class ErrorResponse(

@Json(name="name")
val name: String? = null,

@Json(name="message")
val message: String? = null,

@Json(name="errors")
val errors: Errors? = null,

@Json(name="statusCode")
val statusCode: Int? = null
)

ApiFactory.kt (Let me know if you need the entire code) ApiFactory.kt (如果您需要完整代码,请告诉我)

fun parseError(response: Response<*>): ErrorResponse {
    val converter = ApiFactory.retrofit()
            .responseBodyConverter<ErrorResponse>(
                    ErrorResponse::class.java, arrayOfNulls<Annotation>(0)
            )

    val error: ErrorResponse

    try {
        error = converter.convert(response.errorBody()!!)!!
    } catch (e: IOException) {
        e.printStackTrace()
        return ErrorResponse()
    }

    return error
}

and in the Presenter (I use MVP)并在演示者中(我使用 MVP)

GlobalScope.launch(Dispatchers.Main) {
        try {
            val response = ApiFactory.apiService.LOGIN(username, password)
                    .await()
            val body = response.body()
            body?.let {
            // Handle success or any other stuff
                if (it.statusCode == 200) {
                    mView.onSuccess(it.data!!)
                }
            } ?:
            // This is the else part where your body is null
            // Here is how you use it.
            // Pass the response for error handling
            mView.showMessage(ApiFactory.parseError(response).message!!)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

And thats how you roll it!这就是你如何滚动它! That's All Folks!这就是所有的人!

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

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