Retrofit 2.0 - How to get response body for 400 Bad Request error?

前端 未结 9 1872
旧巷少年郎
旧巷少年郎 2021-01-31 02:33

So when I make a POST API call to my server, I get a 400 Bad Request error with JSON response.

{
    \"userMessage\": \"Blah\",
    \"internalMessage\": \"Bad Re         


        
相关标签:
9条回答
  • 2021-01-31 02:52

    This is how you can handle the response message I am handling for error 500 you can add as much you want

                    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;
                    }
    
    0 讨论(0)
  • 2021-01-31 02:53

    Here is the simplest solution,

    If you want to handle the response from onFailure method:

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

    Or if you are using rxjava Observable with Kotlin, handle it from error body:

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

    Don't forget to properly handle json to class conversion (use try-catch if not sure).

    0 讨论(0)
  • 2021-01-31 02:55

    simply use

     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 讨论(0)
  • 2021-01-31 03:03

    I got similar issue, but existing code was stick to RxJava 2 chain. Here's my solution:

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

    transforming 400-like responses into rx chain is pretty simple:

    Call<Cat> request = catApi.getCat();
    rxified(request, Cat.class).subscribe( (cat) -> println(cat) );
    
    0 讨论(0)
  • 2021-01-31 03:04

    You can do it in your onResponse method, remember 400 is a response status not an error:

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

    And you can handle any response code except 200-300 with Gson like that:

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

    Add this to your build.gradle : compile 'com.google.code.gson:gson:2.7'

    If you want create Pojo class go to Json Schema 2 Pojo and paste your example Json response. Select source type Json and annotation Gson .

    0 讨论(0)
  • 2021-01-31 03:04
    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();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题