I am using Jackson to serialize JSON, but my JSON clients are not Java, and don't use Jackson.
我使用Jackson来序列化JSON,但我的JSON客户端不是Java,也不使用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.
我希望避免循环引用序列化无限递归,每当序列化整个bean会导致无限递归时,序列化bean的id而不是整个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.
每当Jackson开始序列化bean时,它应该看看堆栈是否包含bean。
If the bean is already in the stack, serialize the id instead of the whole bean, thereby avoiding the infinite recursion.
如果bean已经在堆栈中,则序列化id而不是整个bean,从而避免无限递归。
If the bean is not in the stack, push it onto the stack, and serialize the whole bean normally.
如果bean不在堆栈中,则将其推入堆栈,并正常序列化整个bean。
Once Jackson has finished serializing the bean, pop the bean off the stack.
一旦Jackson完成序列化bean,就将bean从堆栈中弹出。
Therefore, I want the following Java to serialize into the following JSON:
因此,我希望以下Java序列化为以下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:
我只知道有两种内置的Jackson处理循环引用的方法,如果我理解它们,它们都不能输出上面的JSON:
-
@JsonIdentityInfo
, which, when best setup, annotating bothA
&B
with:@JsonIdentityInfo,在最佳设置时,使用以下内容注释A和B:
@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:@JsonManagedReference和@JsonBackReference,我必须指定一方为正向,另一方为背面。假设我选择A - > B属性作为前进,然后我得到:
{ "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?
如果没有,我怎么能挂钩杰克逊在我自己的类中维护一个堆栈,实现一些Jackson接口/扩展一些Jackson类,然后使用该堆栈来影响序列化?
1 个解决方案
#1
Jackson does maintain couple of stacks. The older one is at JsonGenerator
level, see getOuputContext()
. That lets you see what is being output physically, that is, which scopes (Object, Array) are open.
杰克逊确实保留了几个筹码。较旧的是JsonGenerator级别,请参阅getOuputContext()。这使您可以看到物理输出的内容,即哪些范围(对象,数组)是打开的。
But Jackson 2.5 added new method, JsonGenerator.getCurrentValue()
, and matching calls from databind, which should additionally give you Object graph view of what is being serialized, at least when combining the two. To access ancestors of the current value, you need to traverse "output context", ask for current value up the output stack.
但Jackson 2.5添加了新的方法JsonGenerator.getCurrentValue(),以及来自databind的匹配调用,它还应该为您提供序列化的对象图形视图,至少在将两者结合使用时。要访问当前值的祖先,您需要遍历“输出上下文”,向输出堆栈请求当前值。
#1
Jackson does maintain couple of stacks. The older one is at JsonGenerator
level, see getOuputContext()
. That lets you see what is being output physically, that is, which scopes (Object, Array) are open.
杰克逊确实保留了几个筹码。较旧的是JsonGenerator级别,请参阅getOuputContext()。这使您可以看到物理输出的内容,即哪些范围(对象,数组)是打开的。
But Jackson 2.5 added new method, JsonGenerator.getCurrentValue()
, and matching calls from databind, which should additionally give you Object graph view of what is being serialized, at least when combining the two. To access ancestors of the current value, you need to traverse "output context", ask for current value up the output stack.
但Jackson 2.5添加了新的方法JsonGenerator.getCurrentValue(),以及来自databind的匹配调用,它还应该为您提供序列化的对象图形视图,至少在将两者结合使用时。要访问当前值的祖先,您需要遍历“输出上下文”,向输出堆栈请求当前值。