android - ejemplo - Retrofit 2.0-¿Cómo obtener el cuerpo de respuesta para 400 Error de solicitud incorrecta?
retrofit send json body (6)
Puedes probar el siguiente código para obtener 400 respuestas. Puede obtener una respuesta de error del método 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().toString());
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
}
}
}
Entonces, cuando hago una llamada POST API a mi servidor, recibo un error 400 Bad Request con respuesta JSON.
{
"userMessage": "Blah",
"internalMessage": "Bad Request blah blah",
"errorCode": 1
}
Lo llamo por
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
}
}
Sin embargo, el problema es que una vez que obtengo la respuesta, onFailure () se invoca para que se llame a // BB. Aquí, no tengo forma de acceder a la respuesta JSON. Cuando registro la solicitud y respuesta de la API, no muestra ninguna respuesta JSON. Y Throwable t es IOException. Sin embargo, extrañamente, cuando hago la misma llamada en Postman, devuelve la respuesta JSON esperada con el código de error 400.
Entonces, mi pregunta es ¿cómo puedo obtener la respuesta json cuando obtengo el error 400 Bad Request? ¿Debo agregar algo a okhttpclient?
Gracias
Así es como puede manejar el mensaje de respuesta que estoy manejando para el error 500 que puede agregar tanto como desee.
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;
}
Puede hacerlo como en su método onResponse
, recuerde que 400 es un estado de respuesta, no un error:
if (response.code() == 400) {
Log.v("Error code 400",response.errorBody().string());
}
Y puede manejar cualquier código de respuesta, excepto 200-300, con Gson
como:
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
}
}
Agrega esto a tu build.gradle
: compile ''com.google.code.gson:gson:2.7''
Si desea crear una clase Pojo
, vaya a Json Schema 2 Pojo y pegue su ejemplo de respuesta Json
. Seleccione el tipo de fuente Json y la anotación Gson .
Tengo un problema similar, pero el código existente se adhiere a la cadena RxJava 2. Aquí está mi solución:
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);
}
});
}
});
}
transformar las respuestas de 400 como en la cadena rx es bastante simple:
Call<Cat> request = catApi.getCat();
rxified(request, Cat.class).subscribe( (cat) -> println(cat) );
Primer paso:
Crea tu clase POJO para respuesta de error. En mi caso, ApiError.java
public class ApiError {
@SerializedName("errorMessage")
@Expose
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage= errorMessage;
}
}
Segundo paso:
Escriba abajo el código en su devolución de llamada 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
}
}
Aquí ApiClient.retrofit
es su instancia de ApiClient.retrofit
que es estática.
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();
}
}
}