【问题标题】:Retrofit 2 - Response body null when response status is 422 (unprocessable entity)改造 2 - 当响应状态为 422(不可处理实体)时,响应正文为空
【发布时间】:2016-03-12 11:54:36
【问题描述】:

我正在使用 Retrofit 在我的网络服务器中发出 POST 请求。

但是,当响应状态为422 (unprocessable entity) 时,我似乎无法获取响应正文。响应正文始终为null

我想知道我是否做错了什么,或者是否有解决方法。因为我在Postman的请求中使用了相同的json,它正常返回body。

这是方法:

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

主体是一个 JsonObject,我没有像文档说的那样进行序列化。但我不认为这是问题所在。

【问题讨论】:

  • 您的 api 是否在 422 错误中返回了一些正文?你是用安卓地图的吗?
  • @DeividiCavarzan 是的,正如我在问题中提到的,当我使用 Postman 发出请求时,它会完美地返回正文。我在两个地方都使用相同的 json 对象。
  • @DeividiCavarzan 关于映射,是的,我做到了。它实际上使用response.body() == null 执行回调中的onResponse(Response&lt;JsonObject&gt; response, Retrofit retrofit)
  • @Erick 你的请求没有完成,所以你面临这个问题..
  • 我建议在发送时拦截你的请求,使用 OkHttp 拦截器,看看你是否发送正确,与 Postman 的比较一下

标签: android json post retrofit


【解决方案1】:

默认情况下,当您的服务器返回错误代码时,response.body() 始终为null。您正在寻找的是response.errorBody()。一种常见的方法是这样的:

    @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
        }
    }

如果您需要更高级的内容,请查看 Interceptorshow to use them

【讨论】:

  • 谢谢.. 但我的 errorBody() 也总是为空.. 我设法让它在没有改造的情况下工作。我奖励你赏金,因为它即将到期
  • 泰。通过拦截器,您可以检查幕后发生的事情并查看原始请求和响应。无论如何,我很高兴你找到了办法:)
【解决方案2】:

我遇到了同样的错误。我的 API 使用 POSTMAN 请求工作,但无法通过 Android 改造调用工作。

起初我尝试使用@Field,但出现错误,但后来我尝试使用@Body,它成功了。

示例改造接口调用

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

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));

【讨论】:

    【解决方案3】:

    那么在这种情况下,您必须转换响应。 看看这个link

    上面的链接中已经提供了所有步骤。

    对于 Kotlin 用户,这里是代码解决方案。

    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(如果您需要完整代码,请告诉我)

    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
    }
    

    Presenter中(我使用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()
            }
        }
    

    这就是你的滚动方式! 就是这样!

    【讨论】:

    • 需要整个代码ApiFactory.kt
    猜你喜欢
    • 1970-01-01
    • 2020-09-26
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多