Как написать сглаживающий десериализатор списка с помощью Джексона?

Я пытаюсь десериализовать JSON определенной структуры в классы Java с помощью Джексона. У меня есть несколько таких классов:

class A {
  private int number1;
  private List<X> list1;
  private int number2;
}

class X {
  private String field1;
  private double value1;
}


class B {
  private String name2;
  private List<Y> list2;
}

class Y {
  private String field2;
}

И я получаю JSON из внешней системы, как показано ниже:

{
  "number1": 1,
  "list1": {
    "elements": [{
      "field1": "Field 1 value 1",
      "value1": 2.2
    }, {
      "field1": "Field 1 value 2"
    }]
  },
  "number2": 2,
}


{
  "name2": "Name 2",
  "list2": {
    "elements": [{
      "field2": "Field 2 value 1"
    }]
  }
}

Все, что я хочу, это написать собственный десериализатор, который мог бы избавиться от этого уровня элементы общим способом (я имею в виду иметь один десериализатор для всех классов). Есть ли простой способ расширить StdDeserializer для этого или мне нужно написать совершенно новый десериализатор с моим собственным алгоритмом?

Вы хоть представляете, сколько псевдонимов существует для name1?

Deadpool 03.02.2019 19:03

Я не понимаю, что это меняет? Это просто техническая проблема.

Andrew Doe 04.02.2019 02:32

мы можем сделать это простым способом, отличным от пользовательского десериализатора

Deadpool 04.02.2019 02:40

В общем, эти JSON могут иметь любую структуру, и я обновил пример выше. Одно можно сказать наверняка, что коллекции будут отправляться так: "имя_коллекции": { "элементы": [{ ... }] } и я пытаюсь избавиться от этого уровня элементы.

Andrew Doe 04.02.2019 23:50

Связано: stackoverflow.com/questions/11747370/…

shmosel 05.02.2019 01:44

Спасибо за ссылку, но это не помогает мне в создании универсального решения, которое позволяет иметь списки на каждом уровне JSON.

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

Ответы 1

Вы можете взглянуть на этот вопрос: Джексон - десериализовать внутренний список объектов в список одного более высокого уровня, который очень похож. Я реализовал там собственный десериализатор, который можно использовать для разных типов с внутренним списком. Ваш пример POJO может выглядеть так:

class A {
    private int number1;

    @JsonDeserialize(using = InnerListDeserializer.class)
    private List<X> list1;
    private int number2;

    // getters, setters
}

РЕДАКТИРОВАТЬ
Если вы не хотите использовать какую-либо аннотацию или пользовательскую десериализацию, вам необходимо создать структуру POJO, которая соответствует заданному JSON. Вам нужно создать средний POJO:

class ListWrapper<T> {

    private List<T> elements;

    // getter, setter, toString, etc
}

Теперь вам нужно обновить классы A и B следующим образом:

class A {
    private int number1;
    private ListWrapper<X> list1;
    private int number2;

    // getters, setters, toString
}

и

class B {

    private String name2;
    private ListWrapper<Y> list2;

    // getters, setters, toString
}

Извините за поздний ответ. Я хочу решить эту проблему более широко и без аннотаций Джексона (я хочу выставить чистые классы POJO без метаданных). Могу предположить, что внешняя система всегда обслуживает коллекции, как в примере JSON (с уровнем элементов).

Andrew Doe 13.02.2019 22:31

Цитата из вашего вопроса: «Все, что я хочу, это написать собственный десериализатор, который мог бы избавиться от этого уровня элементов в общем виде». Итак, теперь вы не хотите реализовывать собственный десериализатор и создавать набор классов POJO, которые подходят для данного JSON?

Michał Ziober 13.02.2019 23:34

Это небольшое недоразумение. Я хочу зарегистрировать глобальный десериализатор в Джексоне, чтобы десериализовать все списки (с уровнем элементов) в общем виде, что для меня означает: без дополнительных аннотаций к модели.

Andrew Doe 17.02.2019 00:54

Я понимаю это сейчас. Это немного сложная проблема. Как вы можете проверить, мой пользовательский десериализатор из другого вопроса использует десериализатор Jsckson по умолчанию для списка. Непростая задача правильно расширить его и десериализовать список с помощью специального десериализатора. Вам нужно знать тип элемента и прочитать все используемые там аннотации. Вы можете попробовать расширить com.fasterxml.jackson.databind.deser.std.CollectionDeseriali‌​zer, но намного проще использовать мой InnerListDeserializer. Если вы не можете изменить классы, используйте функцию MixIn. Если вы думаете, что мой ответ вам не поможет, я могу удалить его.

Michał Ziober 17.02.2019 21:04

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