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

时间:2016-07-07 21:08:26

标签: android retrofit

因此,当我对我的服务器进行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上进行相同的调用时,它确实返回了400错误代码的预期JSON响应。

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

由于

10 个答案:

答案 0 :(得分:34)

您可以在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(getApplicationContext(), mError.getErrorDescription(), 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

答案 1 :(得分:9)

  

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

编辑:从toStringstring的固定方法名称

答案 2 :(得分:3)

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

答案 3 :(得分:2)

第一步:

创建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 :(得分:2)

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 :(得分:1)

这是最简单的解决方案,

如果要处理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)。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

使用类对象处理 ErrorResponse

科特林

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

Java

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

答案 8 :(得分:0)

只需使用

 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 :(得分:0)

如果您通过改造获得 400(错误请求),请首先确保将 API 的输入设置为仅模型 类,如果不是,则将输入请求替换为模型类,然后检查您将获得成功响应。

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