Java Джексон десериализует обычный массив Json или объект Json в один объект Java (POJO) - PullRequest
0 голосов
/ 14 декабря 2018

Я получаю данные из конечной точки API, которая возвращает данные в двух разных ожидаемых форматах json.Один из ответов является ответом об успешном выполнении, а один из ответов является ответом об отказе.Другие конечные точки в API похожи и также имеют формат успеха и неудачи.Для большинства конечных точек я просто десериализирую оба типа ответов в один Java-объект, где для некоторых полей просто заданы значения по умолчанию / null, когда их нет.Моя проблема с этой конечной точкой заключается в том, что ответом об успешном выполнении является массив json, а ответом об ошибке является объект json.Я перепробовал все, чтобы иметь простой способ десериализации обоих этих возможных ответов в один объект Java.

Пример успеха json.

[
    {
        "item1": "somevalue1",
        "item2": "somevalue2"
    },
    {
        "item1": "somevalue3",
        "item2": "somevalue4"
    },
    ..
    ..
]

Пример сбоя json

{
    "success": false,
    "errorMessage": "something went wrong "
}

Мой класс Java, который я сейчас использую, работает для десериализации JSON успеха, но не для JSON сбоя.

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(ArrayList<MyItem> items) {
       this.items = items;
    }

}

И у меня также есть конструктор, который работает для случая сбоя, но не для случая успеха

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(@JsonProperty("success") Boolean success, @JsonProperty("errorMessage") String errorMessage){
        this.success = success == null;
        this.errorMessage = errorMessage;
        this.items = items;
    }

}

Мой код десериализации выглядит примерно так:

ObjectReader objectReader = objectMapper.readerFor(ResponseObject.class);
Object json = objectReader.readValue(inputStream);

Какая бы стратегия я ни пытался сделать, чтобы иметь возможность десериализовать оба случая в общем, кажется неудачной.Если я пытаюсь включить массив json в конструктор с @JsonProperty, то у меня нет имени / значения для ссылки на массив элементов, и код выдает исключение.

Мне нужен способдесериализовать оба ответа в указанном мною формате ResponseObject. Когда я получу ответ об успешном завершении, поле успеха должно быть истинным, errorMessage должно быть нулевым, а элементы должны содержать список MyItem.Когда я получаю ответ об ошибке, успех должен быть ложным, errorMessage должен содержать строковое сообщение, а список элементов должен быть нулевым.

Как мне этого добиться?Или, как еще я могу структурировать свой код для обработки нескольких ожидаемых форматов JSON?Я знаю, что могу десериализовать в TreeMap, проверить формат, а затем снова преобразовать, например, в конечный объект, но я бы хотел пропустить этот промежуточный шаг.

Спасибо за любой совет, который кто-нибудь может дать мне по этому вопросу.один :) 1024 *

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

Если вы добавите POJO для сообщения об ошибке, вы можете добавить второго JsonCreator в свой объект ответа.

public class ErrorResponse {
    private boolean success;
    private String errorMessage;
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public String getErrorMessage() {
        return errorMessage;
    }
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}

Модифицированный объект ResponseObject с 2 JsonCreator

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(List<MyItem> items) {
       this.success = true;
       this.errorMessage = null;
       this.items = items;
    }

    @JsonCreator
    public ResponseObject(ErrorResponse error){
        this.success = error.isSuccess();
        this.errorMessage = error.getErrorMessage();
        this.items = null;
    }

}
0 голосов
/ 14 декабря 2018

Вы можете попытаться сделать суперкласс

public class ResponseObject {

    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    ...
}

и затем организовать сообщения об ошибках и успехах в

public class SuccesResponseObject extends ResponseObject {...}

и

public class FailResponseObject extends ResponseObject {...}

с помощьюсоответствующие конструкторы.Свойства будут расположены в суперклассе.При использовании классов вы должны ссылаться на них как на класс ResponseObject.

...