Retrofit 2.0 - 如何获取 400 Bad Request 错误的响应正文?

问题描述 投票:0回答:11

因此,当我对服务器进行 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
11个回答
65
投票

您可以在

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.gradle
compile 'com.google.code.gson:gson:2.7'

如果您想创建

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


21
投票

您可以尝试以下代码来获得 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


11
投票

使用类对象处理 ErrorResponse

科特林

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

Java

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

8
投票
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(); } } }
    

5
投票

第一步:

创建用于错误响应的 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

 是您的静态改造实例。


4
投票
我遇到了类似的问题,但现有代码坚持 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) );
    

4
投票
这是最简单的解决方案,

如果你想处理 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); }

或者,如果您将 rxjava Observable 与 Kotlin 一起使用,请从错误正文中处理它:

{ 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)。


1
投票
这是处理响应消息的方式 我正在处理错误 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; }
    

1
投票
简单使用

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

0
投票
如果您通过使用改造获得

400(错误请求),请首先确保正在设置API 的输入仅是模型类,如果不是,则用模型类替换输入请求,然后检查您是否会获得成功响应。

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

    

0
投票
要处理响应中的 400 Bad Request 错误,请使用以下代码。

if (response.isSuccessful()) { if (response.body().getStatus().equals(1)) { progressBar.setVisibility(View.GONE); Toast.makeText(UploadPDFActivity.this, "Success", Toast.LENGTH_SHORT).show(); } } else { int statusCode = response.code(); Log.e("hello 4001", "else condition"); if (statusCode == 400) { progressBar.setVisibility(View.GONE); if (!response.isSuccessful()) { JSONObject jsonObject = null; try { jsonObject = new JSONObject(response.errorBody().string()); String entityId = jsonObject.getString("entity_id"); String errorMessage = jsonObject.getString("message"); String errorStatus = jsonObject.getString("status"); Log.e("hello entityId", entityId); Log.e("hello errorMessage", errorMessage); Log.e("hello errorStatus", errorStatus); Toast.makeText(UploadPDFActivity.this, errorMessage, Toast.LENGTH_SHORT).show(); } catch (JSONException | IOException e) { e.printStackTrace(); } } } else { // Handle other error cases } } }
    
© www.soinside.com 2019 - 2024. All rights reserved.