I am using Jackson to serialize JSON, but my JSON clients are not Java, and don't use Jackson.
I want to avoid circular reference serialization infinite recursion by, whenever serializing a whole bean would cause an infinite recursion, serializing the id of the bean instead of the whole bean.
This can be accomplished by maintaining a stack of the current serialization context.
Whenever Jackson starts to serialize a bean, it should see if the stack contains the bean.
If the bean is already in the stack, serialize the id instead of the whole bean, thereby avoiding the infinite recursion.
If the bean is not in the stack, push it onto the stack, and serialize the whole bean normally.
Once Jackson has finished serializing the bean, pop the bean off the stack.
Therefore, I want the following Java to serialize into the following JSON:
Java:
class A {
String id;
B b;
B c;
}
class B {
String id;
A a;
}
class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.id = "a1";
b.id = "b1";
a.b = b;
a.c = b;
b.a = a;
ObjectMapper m = new ObjectMapper();
System.out.println(m.writeValueAsString(a));
System.out.println(m.writeValueAsString(b));
}
}
JSON:
{
"id": "a1",
"b": {
"id": "b1",
"a": "a1"
},
"c": {
"id": "b1",
"a": "a1"
}
}
{
"id": "b1",
"a": {
"id": "a1",
"b": "b1"
}
}
I only know of two built-in Jackson ways to handle circular references, neither of which, if I understand them correctly, can output the above JSON:
@JsonIdentityInfo
, which, when best setup, annotating bothA
&B
with:@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
would output (with a comment indicating the problem):
{ "id": "a1", "b": { "id": "b1", "a": "a1" }, "c": "b1" // problem: value of "c" is b.id instead of b with b.a = a.id } { "id": "b1", "a": { "id": "a1", "b": "b1" } }
@JsonManagedReference
&@JsonBackReference
, for which I have to specify one side as forward, and the other as back. Say I chooseA
->B
properties as forward, then I get:{ "id": "a1", "b": { "id": "b1", "a": "a1" }, "c": { "id": "b1", "a": "a1" } } { "id": "b1" // problem: "a" isn't serialized }
Is there any built-in Jackson way to serialize as I desire?
If not, does Jackson maintain a serialization stack?
If so, how can I access it, and somehow modify the serialization output?
If not, how can I hook into Jackson to maintain a stack in my own classes that implement some Jackson interfaces / extend some Jackson classes, and then use that stack to influence serialization?