Сериализация Джексона 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 не верно) → остановка
Спасибо заранее.
Ответы
Ответ 1
Проверьте следующие ссылки, это может помочь:
Единственный вариант после этого - создать собственный настраиваемый модуль для сериализации/десериализации для вашего типа объекта. см. здесь:
С уважением.
Ответ 2
Недавно я столкнулся с аналогичной проблемой: Jackson - сериализация сущностей с двунаправленными отношениями (избегая циклов)
Итак, решение состоит в том, чтобы перейти на Jackson 2.0 и добавить к классам следующую аннотацию:
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,
property = "@id")
public class SomeEntityClass ...
Это работает отлично.
Ответ 3
Нет поддержки для игнорирования уровня.
Но вы можете заставить Джексона обрабатывать циклические ссылки с 2.0, см., например, "" Джексон 2.0 выпущен" для объяснения того, как использовать @JsonIdentityInfo
.
Ответ 4
Для сериализации по глубине вы можете обратиться к примеру здесь https://github.com/abid-khan/depth-wise-json-serializer
Ответ 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);
}