wake-up-neo.com

Retrofit 2.0 - Wie erhalte ich einen Antworttext für den Fehler "400 Bad Request"?

Wenn ich also einen POST - API-Aufruf an meinen Server mache, erhalte ich einen 400 Bad Request-Fehler mit JSON-Antwort.

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

Ich rufe es an 

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

Das Problem ist jedoch, dass onFailure () aufgerufen wird, sobald ich die Antwort erhalten habe, damit // BB aufgerufen wird. Hier habe ich keine Möglichkeit, auf die JSON-Antwort zuzugreifen. Wenn ich die API-Anforderung und -Antwort protokolliere, wird keine JSON-Antwort angezeigt. Und zu werfen ist t IOException. Seltsamerweise gibt es beim Aufruf von Postman die erwartete JSON-Antwort mit 400-Fehlercode zurück. 

Meine Frage ist also, wie bekomme ich die Json-Antwort, wenn ich den Fehler 400 Bad Request bekomme? Sollte ich etwas zu okhttpclient hinzufügen?

Vielen Dank

20
user2062024

Sie können dies wie in Ihrer onResponse-Methode tun, denken Sie daran, dass 400 ein Antwortstatus und kein Fehler ist:

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

Sie können jeden Antwortcode außer 200-300 mit Gson wie folgt behandeln:

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

Fügen Sie dies Ihrem build.gradle hinzu: compile 'com.google.code.gson:gson:2.7'

Wenn Sie eine Pojo-Klasse erstellen möchten, gehen Sie zu Json Schema 2 Pojo und fügen Sie Ihre Beispielsvariable Json ein. Wählen Sie den Quellentyp Json und die Anmerkung Gson.

30
Yasin Kaçmaz

Sie können den folgenden Code ausprobieren, um 400 Antworten zu erhalten. Sie können eine Fehlerantwort von der errorBody () -Methode erhalten.

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

EDIT: Fester Methodenname von toString bis string

7

Ich habe ein ähnliches Problem bekommen, aber der vorhandene Code wurde an die RxJava 2-Kette gebunden .. Hier ist meine Lösung:

   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 ähnliche Antworten in eine rx-Kette umzuwandeln, ist ziemlich einfach:

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

Erster Schritt:

Erstellen Sie Ihre POJO-Klasse für die Fehlerantwort. In meinem Fall ApiError.Java

public class ApiError {

    @SerializedName("errorMessage")
    @Expose
    private String errorMessage;

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage= errorMessage;
    }
}

Zweiter Schritt:

Schreiben Sie den Code in Ihren API-Callback.

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

Hier ist ApiClient.retrofit Ihre Nachrüstinstanz, die statisch ist.

2
Ekta Bhawsar
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();
        }
    }
}
2
Keshav Gera

So können Sie mit der Antwortnachricht umgehen Ich arbeite mit Fehler 500, den Sie hinzufügen können, so viel Sie möchten

                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
Shivam Mathur