Глобальные настройки Джексона для десериализации массива для реализации пользовательского списка

По умолчанию Джексон использует java.util.ArrayList для десериализации массива JSON. Вместо этого я хочу использовать пользовательскую реализацию. Например, Guava ImmutableList, если значение присутствует, или Collection.emptyList(), если массив JSON пуст или равен нулю.

Я хочу настроить это глобально для ObjectMapper. Есть простой способ сделать это?

PS: Моя версия Джексона 2.9.7

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
0
774
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не думаю, что такой простой способ существует, потому что CollectionDeserializer создает экземпляр коллекции перед синтаксическим анализом. Итак, для этих целей вам нужно создать свой собственный десериализатор.

Но я не уверен=))

Ответ принят как подходящий

Общее решение - использовать пользовательский модуль. Вы можете определить классы, которые вы хотели бы использовать для коллекций. Для Guava есть модуль Maven:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-guava</artifactId>
    <version>x.y.z</version>
</dependency>

Теперь вы можете зарегистрировать свой новый модуль:

ObjectMapper mapper = new ObjectMapper();
// register module with object mapper
mapper.registerModule(new GuavaModule());

Теперь вы можете указать в своем POJO, что хотите иметь неизменяемую реализацию списка.

class Pojo {

    private ImmutableList<Integer> ints;

    public ImmutableList<Integer> getInts() {
        return ints;
    }

    public void setInts(ImmutableList<Integer> ints) {
        this.ints = ints;
    }

    @Override
    public String toString() {
        return "Pojo{" +
                "ints = " + ints + " " + ints.getClass() + '}';
    }
}

и ниже пример:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());

String json = "{\"ints\":[1,2,3,4]}";

System.out.println(mapper.readValue(json, Pojo.class));

печатает:

Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}

Если вы не хотите связывать свои классы POJO с реализацией List, вам нужно добавить некоторую дополнительную конфигурацию, используя класс SimpleModule. Итак, ваш POJO выглядит следующим образом:

class Pojo {

    private List<Integer> ints;

    public List<Integer> getInts() {
        return ints;
    }

    public void setInts(List<Integer> ints) {
        this.ints = ints;
    }

    @Override
    public String toString() {
        return "Pojo{" +
                "ints = " + ints + " " + ints.getClass() + '}';
    }
}

и ваш пример выглядит так:

SimpleModule useImmutableList = new SimpleModule("UseImmutableList");
useImmutableList.addAbstractTypeMapping(List.class, ImmutableList.class);

GuavaModule module = new GuavaModule();

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.registerModule(useImmutableList);

String json = "{\"ints\":[1,2,3,4]}";

System.out.println(mapper.readValue(json, Pojo.class));

Над кодом печатается:

Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}

Когда вы удаляете дополнительный SimpleModule, код выше печатает:

Pojo{ints=[1, 2, 3, 4] class java.util.ArrayList}

Не вижу смысла использовать Collections.emptyList(), если он пустой. Модуль Guava использует RegularImmutableList для непустых и пустых массивов.

Для преобразования null -> empty см. этот вопрос:

  1. Десериализатор Джексона - изменить нулевую коллекцию на пустую

но я рекомендую установить empty в POJO, как показано ниже:

private List<Integer> ints = Collections.emptyList();

Спасибо, Михал, это то, что я искал +1

Łukasz Woźniczka 21.01.2019 16:53

Другие вопросы по теме