我正在使用 SpringMVC 3.2.4 并希望使用 Jackson2 将对象序列化为 JSON 输出。
该对象具有递归属性。如果我尝试使用默认的 Jackson ObjectMapper 对其进行序列化,则会出现递归错误。我意识到我可以使用 @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)然而,为了防止递归,我实际上希望递归能够更容易地在 mustache 模板中解析。但是,我想限制递归级别。
无论如何要指定 Jackson 序列化程序只递归 1 个级别?如果我需要创建自己的序列化程序,是否可以注册它以便它仅用于特定的对象类?
正如一些评论所表明的那样,关于 SO 的另一个问题与此问题密切相关:Jackson JSON serialization, recursion avoidance by level defining .但是,在那个问题中,接受的答案(以及其他答案)都表明如何通过使用 @JsonIdentityInfo 来避免 jackson 的递归。 .在这种特殊情况下,我不打算限制它;而是我想要它。但是,我只想限制递归的深度。
此外,引用的 SO 问题提供了一些 Jackson 文档的链接;我已经有了这些文档,但坦率地说,Jackson 文档非常缺乏。它们指示如何注册序列化程序,但不指示它需要如何构建。也没有关于如何确定序列化程序的递归级别的任何指示。最后,没有说明是否/如何在 Spring 中为 Jackson 注册序列化程序以应用于特定类型的类。
请您参考如下方法:
如果有人遇到此问题,则可以限制递归深度。 @JsonIdentityInfo, @JsonBackReference, @JsonManagedReference仅针对某些情况提供确定的解决方案。
我遇到的一个问题 @JsonIdentityInfo是有时一级子级由于另一个子级的递归深度而不会被序列化,例如:
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id")
class A {
private long id;
private B last;
// Getters, setters...
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id")
class B {
private long id;
private A a;
private C c1;
private C c2;
// Getters, setters...
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id")
class C {
private long id;
private Set<A> as;
private B last;
// Getters, setters...
}
在我的例子中这会产生什么:
{
"id": 1,
"b": {
"id: 2,
"a": { ... },
"c1": { ... },
"c2": 4
}
}
序列化器会下降到子节点
A a;和
C c1但不是
C c2对我来说,让一级 child 连载更重要。
另一个问题 是不是所有 child 的序列化深度都一样。
解决方案:
在对象序列化期间忽略关系并根据深度将它们添加到序列化器方法中。
class A {
private long id;
@JsonIgnore
private B last;
public ObjectNode toJson(int depth) {
depth = depth - 1;
ObjectNode node = (new ObjectMapper()).convertValue(this, ObjectNode.class);
if (depth > 0) {
// Descend into relations
ObjectNode b = b.toJson(depth);
node.set("b", b);
}
return node;
}
这将下降到每个子级的深度级别,最后一个对象将没有关系,因此是递归截止点。
现在我可以这样做:
(new A()).toJson(3)这将序列化对象
A与
B关系下降到对象
B序列化它会回到
A但不会下降回
B再次。它将下降到
C然后回到
B到达最后的分界点。
效果很好,您可以根据需要调整深度。




