当前位置: 首页 > 知识库问答 >
问题:

Jackson JSON序列化-指定递归级别

程成天
2023-03-14

我正在使用SpringMVC 3.2.4,并希望使用Jackson2将对象序列化为JSON输出。

对象具有递归属性。如果我尝试使用默认的Jackson ObjectMapper序列化它,我会得到一个递归错误。我意识到我可以使用@JsonIdtyInfo(生成器=ObjectIdGenerator。IntSequengGenerator.class)来防止递归,然而,我实际上希望递归能够使在胡子模板中解析更容易。然而,我想限制递归级别。

是否需要指定Jackson序列化程序只递归1级?如果我需要创建自己的序列化程序,我可以注册它,使其仅用于特定的对象类吗?

正如几条评论所指出的,已经有另一个问题与此密切相关:Jackson JSON序列化,通过级别定义避免递归。然而,在这个问题中,公认的答案(以及其他答案)都表明了如何通过使用@JsonIdentityInfo避免Jackson的递归。在这种特殊情况下,我不想限制它;而是我想要它。但是,我只想限制递归的深度。

此外,参考的SO问题提供了指向一些Jackson文档的链接;我已经有了医生,但坦率地说,杰克逊医生非常缺乏。它们指示如何注册序列化程序,但不指示需要如何构造序列化程序。也没有任何迹象表明如何确定序列化程序的递归级别。最后,没有迹象表明是否/如何在Spring中为Jackson注册一个序列化程序以应用于特定类型的类。

共有2个答案

宇文鸿振
2023-03-14

可以使用包含最大深度的线程本地整数来限制序列化深度。在递归getter中,根据限制检查当前节点的深度,如果达到限制,则返回null。只有当您可以从节点的内部状态计算当前节点深度时,这才有效。

请参阅此答案中的示例代码。

袁英豪
2023-03-14

如果有人遇到这个问题,可以限制递归深度@JsonIdentityInfo、@JsonBackReference、@JsonManagedReference仅在某些情况下提供ok解决方案。

我在@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
  }
}

serialiser会下降到childAcC1但不是cC2对我来说,将一级子级序列化更重要。

另一个问题是序列化深度并不总是相同的所有儿童。

解决方案:在对象序列化过程中忽略关系,并根据深度将它们添加到serialiser方法中。

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;
}

这将下降到每个子级的深度级别,最后一个对象将没有关系,因此递归截止点。

现在我可以做:(新的A()。toJson(3)这将序列化对象AB关系,然后下降到对象B序列化它将返回A,但不会再次下降到B。然后下降到C,然后返回到B,到达最后的分界点。

工作得很好,你可以根据自己的需要调整深度。

 类似资料:
  • 问题内容: 我使用Jackson库将我的pojo对象序列化为表示形式。例如,我有A类和B类: 如果我要序列化类A中的对象,则有可能在序列化时获得递归。我知道我可以通过使用停止它。 是否可以通过深度级别限制序列化? 例如,如果级别为2,则序列化将以这种方式进行: 序列化一个,级别= 0(0 <2正常)->序列化 序列化ab,级别= 1(1 <2 ok)->序列化 序列化ABA,级别= 2(2 <2不

  • 序列化a,级别=0(0<2确定)->序列化 序列化A.B,级别=1(1<2确定)->序列化 序列化A.B.A,级别=2(2<2不为真)->停止 提前道谢。

  • 问题内容: 我有一个带有自我参照字段的模型,称为parent。模型: 序列化器: 现在,我要序列化区域的父级及其父级及其父级,直到父级为none。我发现了针对孩子而不是父母的递归序列化方法。我怎样才能做到这一点? 问题答案: 尝试在此处使用SerializerMethodField: 我不确定DRF是否有内置方法,但是您可以使用查询来获取所需的方法。

  • 问题内容: 我正在尝试将一些较旧的工作转换为使用Newtonsoft JSON.NET。使用该方法的默认处理(例如,如果未指定目标类型)是为内部对象返回a 。 这实际上是JSON真正有用的基本类型,因为它也恰好是JSON使用的基础类型,并且是动态类型最明智的内部实现。 如果我指定这种类型,例如: JSON.NET将正确反序列化最外部的对象结构,但是它将为任何内部结构返回一个类型。我真正需要的是将相

  • 问题内容: 我如何反序列化此json: 使用Google GSON? 问题答案: 要反序列化JSON,您需要为递归接口使用自定义反序列化器。在这种类中,您需要检查JSON并确定要实例化为JSON本身的type字段的类。在这里,您有一个我为您编写的示例基本解串器。 当然,管理边界事件可以得到改善(例如,如果没有类型字段,会发生什么情况?)。 这是我的代码的结果:

  • 问题内容: 我有一个树对象结构,需要进行序列化,并且我希望每次能够使用jackson(或任何其他库-我打开)基于参数来控制序列化的深度。 我的课是这样的: 这是我想根据深度级别获得的2个序列化json的示例 深度级别设置为3 深度级别设置为2 有什么方法可以控制递归对象中序列化的深度? 谢谢 问题答案: 您需要实现自定义序列化程序,在其中需要计算已经处理的对象的数量。对于每个序列化过程,我们需要在