volley studio implementar example android retrofit

android - studio - Obteniendo JSON del objeto RetrofitError usando Retrofit



retrofit post (9)

Two-Liner con getBodyAs para obtener un objeto JSON.

JsonObject responseAsJson = (JsonObject) retrofitError.getBodyAs(JsonElement.class); String message = responseAsJson.get("error").getAsString(); //=> "Username already in use"

Confirmado trabajando en Retrofit 1.x. No estoy seguro de qué cambios son necesarios para Retrofit 2.x.

Estoy usando la biblioteca Retrofit para hacer llamadas REST a un servicio que estoy usando.

Si realizo una llamada de API a mi servicio y tengo un error, el servicio devuelve un poco de JSON junto con el error de HTTP estándar. Usando el objeto RetrofitError incluido en la devolución de llamada fallida, puedo encontrar el código de estado HTTP y varias otras cosas, sin embargo, no puedo recuperar el JSON que el servicio envía de vuelta.

Por ejemplo, supongamos que realizo una llamada a la API donde intento crear un usuario. Si el nombre de usuario ya existe, el servicio devolverá un código de error 400 junto con algunos JSON como este:

{"error":"Username already in use"}

Debido a que un simple código de error 400 no es lo suficientemente específico, realmente necesito acceder al JSON que se devuelve.

¿Alguien sabe cómo puedo obtener estos datos JSON? He intentado buscar en todos los campos del objeto RetrofitError y no puedo encontrarlo en ningún lado. ¿Hay algo adicional que deba estar haciendo?


@LukaCiko respuesta no funciona ahora para mí en la actualización 1.6.1. Aquí como lo estoy haciendo ahora:

@Override public void failure(RetrofitError retrofitError) { String json = new String(((TypedByteArray)retrofitError.getResponse().getBody()).getBytes()); //own logic for example ExampleHandlerError error = new Gson().fromJson(json, ExampleHandlerError.class); }


Entonces, después de un poco más de cacería, encontré la respuesta.

Aquí está mi devolución de llamada por error:

@Override public void failure(RetrofitError retrofitError) { String serverError = null; try { serverError = extractServerError(retrofitError.getResponse().getBody().in()); } catch (Exception e) { Log.e("LOG_TAG", "Error converting RetrofitError server JSON", e); } if (serverError!=null) { Log.i(LOG_TAG, serverError); } Intent intent = new Intent(ACTION_REGISTRATION_ERROR); intent.putExtra("ServerError", serverError); LocalBroadcastManager.getInstance(FamDooApplication.CONTEXT).sendBroadcastSync(intent); }

Y aquí está el método que se llama para extraer el error del servidor:

public static String extractServerError(java.io.InputStream is) { String serverError = null; String serverErrorDescription = null; try { String s = convertStreamToString(is); JSONObject messageObject = new JSONObject(s); serverError = messageObject.optString("error"); serverErrorDescription = messageObject.optString("error_description"); if (serverErrorDescription!=null && !serverErrorDescription.equals("")) { return serverErrorDescription; } else { return serverError; } //String serverStack = messageObject.getString("stack"); } catch (Exception e) { Log.e("Basemodel", "Error converting RetrofitError server JSON", e); } return ""; }

Esto extraerá la información de error enviada por el servicio que está codificada en el JSON.


Estaba teniendo lo mismo. Mi problema era un campo long que provenía del servidor como una String vacía "" . Retrofit estaba dando NumberFormatException porque parece que Gson no convierte una cadena vacía en long (sugiero que sea 0L o algo así). Entonces tuve que cambiar:

long errorCode;

a

String errorCode;

Como se dijo antes, no tuve acceso al mensaje JSON al depurar. Finalmente encontré el error usando la página de RequestMaker, tal vez ayuda a otra persona

http://requestmaker.com/


Prueba este código

@Override public void failure(RetrofitError error) { String json = new String(((TypedByteArray)error.getResponse().getBody()).getBytes()); Log.v("failure", json.toString()); }

con Retrofit 2.0

@Override public void onFailure(Call<Example> call, Throwable t) { String message = t.getMessage(); Log.d("failure", message); }


Puede usar el método getBodyAs del objeto RetrofitError . Convierte la respuesta a un objeto Java de forma similar a otras conversiones de modificación. Primero defina una clase que describa su respuesta de error JSON:

class RestError { @SerializedName("code") public int code; @SerializedName("error") public String errorDetails; }

A continuación, utilice el método mencionado anteriormente para obtener el objeto que describe el error con más detalle.

catch(RetrofitError error) { if (error.getResponse() != null) { RestError body = (RestError) error.getBodyAs(RestError.class); log(body.errorDetails); switch (body.code) { case 101: ... case 102: ... } } }

Retrofit 2.0 cambió la forma en que las respuestas de error son convertidor. Necesitará obtener el convertidor correcto con el método responseBodyConverter y usarlo para convertir el cuerpo de error de la respuesta. Exceptuando el manejo de excepciones, esto sería:

Converter<ResponseBody, RestError> converter = retrofit.responseBodyConverter(RestError.class, new Annotation[0]); RestError errorResponse = converter.convert(response.errorBody());


Recopilo muchas respuestas y escribí algunos códigos para lograr algo mejor:

{ "errors": { "email": [ "Email not valid.", "Unable to find the user [email protected]." ] } }

Tomo todos los artículos en ''correo electrónico'' y los exhibo concatenados con Guava Joiner:

String json = new String(((TypedByteArray)error.getResponse() .getBody()).getBytes()); Map<String, Object> map = new Gson().fromJson( json, new TypeToken<Map<String, Map<String, List<String>>>>() {}.getType()); try { List<String> errorsEmail = (List<String>) ((Map)map.get("errors")).get("email"); Toast.makeText(getApplicationContext(), Joiner.on("/n") .join(errorsEmail), Toast.LENGTH_SHORT).show(); } catch(Exception e){ Log.e(Constants.TAG, e.getMessage()); }


Una forma mucho más ordenada de hacer esto es crear una clase que pueda hacer el análisis sintáctico / conversión para usted, uno al que pueda llamar en cualquier momento y en cualquier lugar.

public class ApiError { public String error = "An error occurred"; public ApiError(Throwable error) { if (error instanceof HttpException) { String errorJsonString = null; try { errorJsonString = ((HttpException) error).response().errorBody().string(); } catch (IOException e) { e.printStackTrace(); } JsonElement parsedString = new JsonParser().parse(errorJsonString); this.error = parsedString.getAsJsonObject() .get("error") .getAsString(); } else { this.error = error.getMessage() != null ? error.getMessage() : this.error; } } }

Ahora puedes usar esto en cualquier lugar, como

ApiError error = new ApiError(error) error.error

Esto es todo de esta publicación del blog (que escribí).


Usando esto puedes obtener el cuerpo del error

if (response != null && response.errorBody() != null) { JSONObject jsonObject = new JSONObject(response.errorBody().string()); String error = jsonObject.getString("error"); }