【问题标题】:Jackson JSON serialization, recursion avoidance by level definingJackson JSON序列化,通过级别定义避免递归
【发布时间】:2012-04-28 19:38:50
【问题描述】:

我使用 Jackson 库将我的 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 序列化
  • 序列化 a.b,级别 =1 (1 序列化
  • 序列化 a.b.a,级别 = 2(2 停止

提前致谢。

【问题讨论】:

  • 您是否能够最终找到一种方法来指定您希望序列化发生的递归深度?
  • 我通过在引用的实体上使用@JsonIgnore 解决了(带有递归),所以我不包含在序列化中。当我需要特定实例时,我已经有了 ID,然后我会进行额外的调用以获取实例。我没有使用通用的解决方案,幸好我的案例很少。

标签: java json serialization jackson


【解决方案1】:

我最近遇到了类似的问题:Jackson - serialization of entities with birectional relationships(避免循环)

所以解决方案是升级到 Jackson 2.0,并在类中添加以下注释:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, 
                  property = "@id")
public class SomeEntityClass ...

这很好用。

【讨论】:

  • 这真是个好方法。但是你知道限制图形深度的方法吗?
  • 很好,谢谢。注意:property的默认值是“@id”,这里可以省略(见JsonIdentityInfo源码=> String property() default "@id";)
【解决方案2】:

检查以下链接,它可能会有所帮助:

之后唯一的选择是为您的对象类型创建您自己的用于序列化/反序列化的自定义模块。看这里:

问候。

【讨论】:

    【解决方案3】:

    不支持基于级别的忽略。

    但是您可以让 Jackson 使用 2.0 处理循环引用,例如“Jackson 2.0 released”以了解如何使用 @JsonIdentityInfo 的说明。

    【讨论】:

    【解决方案4】:

    如果您只想将自己限制在一个级别(即:您转到当前对象的子对象而不是进一步),@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 注释的字段。或者,您可以使用 Object 类或任何常见的超类使用 @JsonView 注释所有其他字段:

    class A {
      @JsonView(Object.class) private int id;
      @JsonView(A.class) private B b;
    
      constructors...
      getters and setters
    }
    

    【讨论】:

      【解决方案5】:

      关于深度序列化,你可以参考这里的例子https://github.com/abid-khan/depth-wise-json-serializer

      【讨论】:

        【解决方案6】:

        在某些情况下,您可以使用保持最大深度的线程本地整数来限制序列化深度。看到这个answer

        【讨论】:

          【解决方案7】:

          经过几个月的大量研究,我实现了自己的解决方案,以使我的域不受杰克逊依赖项的影响。

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

          【讨论】:

            猜你喜欢
            • 2014-01-11
            • 1970-01-01
            • 1970-01-01
            • 2021-03-10
            • 2016-09-08
            • 1970-01-01
            • 2011-04-12
            • 2013-01-18
            • 2014-08-02
            相关资源
            最近更新 更多