[android] Получение JSON из объекта RetrofitError с использованием Retrofit


Answers

Попробуйте этот код

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

с дооснащением 2.0

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

Я использую библиотеку Retrofit для вызова REST на службу, которую я использую.

Если я вызову API для своей службы и имею отказ, служба возвращает бит JSON вместе со стандартным сообщением об ошибке HTTP. Используя объект RetrofitError включенный в обратный вызов отказа, я могу найти код состояния HTTP и несколько других вещей, однако я не могу получить JSON, который служба отправляет обратно.

Например, допустим, я звоню в API, где я пытаюсь создать пользователя. Если имя пользователя уже существует, служба вернет код ошибки 400 вместе с некоторым JSON следующим образом:

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

Поскольку простой код ошибки 400 не является достаточно конкретным, мне действительно нужен доступ к возвращаемому JSON.

Кто-нибудь знает, как я могу получить данные JSON? Я пробовал смотреть на каждое поле объекта RetrofitError и не могу найти его нигде. Есть ли что-то дополнительное, что мне нужно делать?




Два-Liner с getBodyAs для получения объекта JSON.

JsonObject responseAsJson = (JsonObject) retrofitError.getBodyAs(JsonElement.class);

String message = responseAsJson.get("error").getAsString(); //=> "Username already in use"

Подтверждена работа в Retrofit 1.x. Не уверен, какие изменения необходимы для Retrofit 2.x.




Более простой способ сделать это - создать класс, который может выполнить синтаксический анализ / преобразование для вас, которое вы можете вызывать в любое время и в любом месте.

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

Теперь вы можете использовать это в любом месте, например

ApiError error = new ApiError(error)
error.error

Это все из этого сообщения в блоге (которое я написал).




Я компилирую много ответов и написал код для достижения чего-то более приятного:

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

Я беру все элементы в «электронной почте» и отображаю их конкатенацией с 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());
}



Related