Подтвердить что ты не робот

Сериализация Джексона JSON, предотвращение рекурсии путем определения уровня

Я использую библиотеку Джексона для сериализации моих объектов pojo в представлении JSON. Например, у меня есть класс A и класс B:

class A {
  private int id;
  private B b;

  constructors...
  getters and setters
}

class B {
  private int ind;
  private A a;

  constructors...
  getters and setters
}

Если я хочу сериализовать объект из класса A, есть определенная возможность получить рекурсию, когда она сериализована. Я знаю, что могу остановить его, используя @JsonIgnore.

Можно ли ограничить сериализацию уровнем глубины?

Например, если уровень равен 2, сериализация будет идти следующим образом:

  • сериализовать a, level = 0 (0 < 2 ok) → сериализовать
  • serialize a.b, level = 1 (1 < 2 ok) → сериализовать
  • serialize a.b.a, level = 2 (2 < 2 не верно) → остановка

Спасибо заранее.

4b9b3361

Ответ 1

Проверьте следующие ссылки, это может помочь:

Единственный вариант после этого - создать собственный настраиваемый модуль для сериализации/десериализации для вашего типа объекта. см. здесь:

С уважением.

Ответ 2

Недавно я столкнулся с аналогичной проблемой: Jackson - сериализация сущностей с двунаправленными отношениями (избегая циклов)

Итак, решение состоит в том, чтобы перейти на Jackson 2.0 и добавить к классам следующую аннотацию:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, 
                  property = "@id")
public class SomeEntityClass ...

Это работает отлично.

Ответ 3

Нет поддержки для игнорирования уровня.

Но вы можете заставить Джексона обрабатывать циклические ссылки с 2.0, см., например, "" Джексон 2.0 выпущен" для объяснения того, как использовать @JsonIdentityInfo.

Ответ 5

Если вы хотите ограничить себя только одним уровнем (то есть: вы переходите к дочерним элементам текущего объекта, а не далее), есть простое решение с @JsonView.

В каждом поле, которое является ссылкой на другой объект, аннотируйте его текущим классом как ваш вид:

class A {
  private int id;
  @JsonView(A.class) private B b;

  constructors...
  getters and setters
}

class B {
  private int ind;
  @JsonView(B.class) private A a;

  constructors...
  getters and setters
}

Затем, при сериализации, используйте класс объекта в качестве вашего представления. Сериализация экземпляра A будет выглядеть примерно так:

{
  id: 42,
  b: {
    id: 813
  }
}

Убедитесь, что для параметра DEFAULT_VIEW_INCLUSION установлено значение true, или поля без аннотации @JsonView не будут отображаться. Кроме того, вы можете аннотировать все остальные поля с помощью @JsonView с использованием класса Object или любого обычного суперкласса:

class A {
  @JsonView(Object.class) private int id;
  @JsonView(A.class) private B b;

  constructors...
  getters and setters
}

Ответ 6

В некоторых случаях вы можете ограничить глубину сериализации, используя локальное целое число нитей, поддерживающее максимальную глубину. См. Этот ответ.

Ответ 7

Через несколько месяцев и много исследований я внедрил свое собственное решение, чтобы сохранить мой домен без зависимостей Jackson.

public class Parent {
    private Child child;
    public Child getChild(){return child;} 
    public void setChild(Child child){this.child=child;}
}

public class Child {
    private Parent parent;
    public Child getParent(){return parent;} 
    public void setParent(Parent parent){this.parent=parent;}
}

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

public interface BidirectionalDefinition {

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Parent.class)
    public interface ParentDef{};

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Child.class)
    public interface ChildDef{};

}

После этого можно настроить конфигурацию отображения объекта:

ObjectMapper om = new ObjectMapper();
Class<?>[] definitions = BidirectionalDefinition.class.getDeclaredClasses();
for (Class<?> definition : definitions) {
    om.addMixInAnnotations(definition.getAnnotation(JsonIdentityInfo.class).scope(), definition);
}