【问题标题】:Retrofit 2.0 - How to get response body for 400 Bad Request error?Retrofit 2.0 - 如何获取 400 Bad Request 错误的响应正文?
【发布时间】:2016-11-10 08:26:32
【问题描述】:

因此,当我对我的服务器进行 POST API 调用时,我收到带有 JSON 响应的 400 Bad Request 错误。

{
    "userMessage": "Blah",
    "internalMessage": "Bad Request blah blah",
    "errorCode": 1
}

我叫它

Call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //AA
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        //BB
    }
}

但是问题是,一旦我得到响应,就会调用 onFailure() 以便调用 //BB。在这里,我无法访问 JSON 响应。 当我记录 api 请求和响应时,它根本不显示 JSON 响应。 Throwable t 是 IOException。然而,奇怪的是,当我在 Postman 上进行相同的调用时,它确实返回了预期的 JSON 响应和 400 错误代码。

所以我的问题是当我收到 400 Bad Request 错误时如何获得 json 响应?我应该向 okhttpclient 添加一些内容吗?

谢谢

【问题讨论】:

标签: android retrofit


【解决方案1】:

您可以在 onResponse 方法中执行此操作,记住 400 是响应状态而不是错误:

if (response.code() == 400) {              
    Log.v("Error code 400",response.errorBody().string());
}

您可以像这样使用Gson 处理任何响应代码除了 200-300

if (response.code() == 400) {
   Gson gson = new GsonBuilder().create();
   ErrorPojoClass mError=new ErrorPojoClass();
   try {
       mError= gson.fromJson(response.errorBody().string(),ErrorPojoClass.class);
       Toast.makeText(context, mError.getDescription(), Toast.LENGTH_LONG).show();
   } catch (IOException e) {
       // handle failure to read error
   }        
}

将此添加到您的build.gradlecompile 'com.google.code.gson:gson:2.7'

如果您想创建 Pojo 类,请转到 Json Schema 2 Pojo 并粘贴您的示例 Json 响应。选择源类型 Json 和注释 Gson

【讨论】:

  • 正如我所写,onResponse() 根本没有执行。而是执行 onFailure() ,因此我无法访问响应对象:(
  • @user2062024 您是否尝试登录call.request().body().toString() 并查看有什么问题。通常它必须进入 onResponse ,但如果你提供更多代码,如果可能的话 Postman 截图,我会考虑。
  • @slanecek 我也在使用 Retrofit 并尝试了我的代码。试图用坏身体请求。它转到 onResponse。
  • @YasinKaçmaz 你是对的,我的错。 RC 400 在 Retrofit 1.x 中是一个错误
  • 难怪我不能通过调用 response.body().string() 得到结果...感谢分享实际的方法是这样调用 response.errorBody().string( )
【解决方案2】:

您可以尝试以下代码来获得 400 响应。您可以从 errorBody() 方法获得错误响应。

Call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //get success and error response here
 if (response.code() == 400) {
                if(!response.isSuccessful()) {
                    JSONObject jsonObject = null;
                    try {
                        jsonObject = new JSONObject(response.errorBody().string());
                        String userMessage = jsonObject.getString("userMessage");
                        String internalMessage = jsonObject.getString("internalMessage");
                        String errorCode = jsonObject.getString("errorCode");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        //get failure response here
    }
}
}

编辑:将方法名称从toString 改为string

【讨论】:

    【解决方案3】:
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        DialogHelper.dismiss();
    
        if (response.isSuccessful()) {
            // Success
        } else {
            try {
                JSONObject jObjError = new JSONObject(response.errorBody().string());
                Toast.makeText(getContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    }
    

    【讨论】:

    • 工作就像一个魅力!
    • 是的,工作!太棒了!
    【解决方案4】:

    第一步:

    为错误响应创建您的 POJO 类。就我而言,ApiError.java

    public class ApiError {
    
        @SerializedName("errorMessage")
        @Expose
        private String errorMessage;
    
        public String getErrorMessage() {
            return errorMessage;
        }
    
        public void setErrorMessage(String errorMessage) {
            this.errorMessage= errorMessage;
        }
    }
    

    第二步:

    在您的 api 回调中编写以下代码。

    Call.enqueue(new Callback<RegistrationResponse>() {
         @Override
         public void onResponse(Call<RegistrationResponse> call, Response<RegistrationResponse> response) 
         {
             if (response.isSuccessful()) {
                 // do your code here
             } else if (response.code() == 400) {
                 Converter<ResponseBody, ApiError> converter =
                                ApiClient.retrofit.responseBodyConverter(ApiError.class, new Annotation[0]);
    
                        ApiError error;
    
                        try {
                            error = converter.convert(response.errorBody());
                            Log.e("error message", error.getErrorMessage());
                            Toast.makeText(context, error.getErrorMessage(), Toast.LENGTH_LONG).show();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
             }
         }
    
         @Override
         public void onFailure(Call<RegistrationResponse> call, Throwable t) {
             //do your failure handling code here
         }
    }
    

    这里ApiClient.retrofit 是您的静态改造实例。

    【讨论】:

      【解决方案5】:

      我遇到了类似的问题,但现有代码坚持使用 RxJava 2 链。 这是我的解决方案:

         public static <T> Observable<T> rxified(final Call<T> request, final Class<T> klazz) {
          return Observable.create(new ObservableOnSubscribe<T>() {
      
              AtomicBoolean justDisposed = new AtomicBoolean(false);
      
              @Override
              public void subscribe(final ObservableEmitter<T> emitter) throws Exception {
      
                  emitter.setDisposable(new Disposable() {
                      @Override
                      public void dispose() {
                          request.cancel();
                          justDisposed.set(true);
                      }
      
                      @Override
                      public boolean isDisposed() {
                          return justDisposed.get();
                      }
                  });
      
                  if (!emitter.isDisposed())
                      request.enqueue(new Callback<T>() {
                          @Override
                          public void onResponse(Call<T> call, retrofit2.Response<T> response) {
                              if (!emitter.isDisposed()) {
                                  if (response.isSuccessful()) {
                                      emitter.onNext(response.body());
                                      emitter.onComplete();
      
                                  } else {
                                      Gson gson = new Gson();
                                      try {
                                          T errorResponse = gson.fromJson(response.errorBody().string(), klazz);
                                          emitter.onNext(errorResponse);
                                          emitter.onComplete();
                                      } catch (IOException e) {
                                          emitter.onError(e);
                                      }
                                  }
                              }
                          }
      
                          @Override
                          public void onFailure(Call<T> call, Throwable t) {
                              if (!emitter.isDisposed()) emitter.onError(t);
                          }
                      });
              }
          });
      }
      

      将类似 400 的响应转换为 rx 链非常简单:

      Call<Cat> request = catApi.getCat();
      rxified(request, Cat.class).subscribe( (cat) -> println(cat) );
      

      【讨论】:

        【解决方案6】:

        这是最简单的解决方案,

        如果要处理来自 onFailure 方法的响应:

        @Override
        public void onFailure(Call<T> call, Throwable t) {
            HttpException httpException = (HttpException) t;
            String errorBody = httpException.response().errorBody().string();
            // use Gson to parse json to your Error handling model class
            ErrorResponse errorResponse = Gson().fromJson(errorBody, ErrorResponse.class);
        }
        

        或者,如果你在 Kotlin 中使用 rxjava Observable,则从错误正文中处理它:

        { error ->
            val httpException :HttpException = error as HttpException
            val errorBody: String = httpException.response().errorBody()!!.string()
            // use Gson to parse json to your Error handling model class
            val errorResponse: ErrorResponse = 
               Gson().fromJson(errorBody, ErrorResponse::class.java)
        }
        

        不要忘记正确处理 json 到类的转换(如果不确定,请使用 try-catch)。

        【讨论】:

          【解决方案7】:

          用你的类对象处理 ErrorResponse

          科特林

          val errorResponse = Gson().fromJson(response.errorBody()!!.charStream(), ErrorResponse::class.java)
          

          Java

          ErrorResponse errorResponse = new Gson().fromJson(response.errorBody.charStream(),ErrorResponse.class)
          

          【讨论】:

            【解决方案8】:

            简单地使用

             if (throwable is HttpException && (throwable!!.code() == 400 || throwable!!.code()==404)){
                                           var responseBody = throwable!!.response()?.errorBody()?.string()
                                           val jsonObject = JSONObject(responseBody!!.trim())
                                           var message = jsonObject.getString("message")
                                           tvValMsg.set(message)
                                        } 
            

            【讨论】:

              【解决方案9】:

              这是处理响应消息的方式 我正在处理错误 500,您可以添加任意数量的内容

                              switch (response.code()) {
                                  case HttpURLConnection.HTTP_OK:
                                      break;
                                  case HttpURLConnection.HTTP_UNAUTHORIZED:
                                      callback.onUnAuthentic();
                                      break;
                                  case HttpURLConnection.HTTP_INTERNAL_ERROR:
                                      try {
                                          String errorResponse = response.errorBody().string();
                                          JSONObject object = new JSONObject(errorResponse);
                                          String message = "Error";
                                          if (object.has("Message"))
                                              message = String.valueOf(object.get("Message"));
                                          callback.onError(message);
                                      } catch (IOException e) {
                                          e.printStackTrace();
                                      }
                                      break;
                                  case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
                                  case HttpURLConnection.HTTP_CLIENT_TIMEOUT:
                                  default:
                                      callback.onNetworkError();
                                      break;
                              }
              

              【讨论】:

                【解决方案10】:

                如果你得到 400(Bad Request) 通过使用改造首先确保设置 API 的输入是 Only Model 类,如果没有,则将输入请求替换为模型类,然后检查你会得到成功响应。

                @POST("api/users/CreateAccount")
                Call<CreateAccount> createAccount(@Body CreateAccount model, @Header("Content-Type") String content_type);
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-02-22
                  • 2020-11-17
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多