【问题标题】:Serialization of @ManyToOne object with customized child object in JPA/Jackson在 JPA/Jackson 中使用自定义子对象序列化 @ManyToOne 对象
【发布时间】:2019-01-23 09:28:01
【问题描述】:

我有两个具有双向@OneToMany/@ManyToOne 关系的实体类。当我序列化Class A 时,我不想在A 类中有整个Class B,只有id 字段。但是,B 类仍然需要作为 A 类中的对象出现,而不仅仅是属性。我怎样才能做到这一点?我正在使用 JPA:2.2/Jackson:2.9.0

@Entity
public class A {

    private long id;

    @ManyToOne
    private B b;

    // ...
}

@Entity
public class B {

    private long id;
    private String str;
    private boolean bool;

    @OneToMany
    Set<A> aList;
    // ...
}

A类的期望结果:

{
    "id" : 123;
    "b" : {
        "id" : 321;
    }
}

【问题讨论】:

  • 您尝试过使用@JsonIgnore 注释吗?或者你可以简单地删除 B 中的 A 对象,它仍然具有 ManyToOne 关系
  • @Mustahsan 我希望能够独立地获取/序列化 B 类。添加@JsonIgnore 会出现问题,因为这样我将永远不会访问对象内的那些字段。(?)Json 结构应该在问题中呈现
  • 在A的对象前添加@JsonIgnore
  • 对,但是我不会在 A 类中得到"b" : { "id" : 321; },对吧?
  • 你会在 A 中得到它 我要求在 OneToMany 之前的 B 类中 A 的对象声明之前添加注释

标签: java json serialization jackson


【解决方案1】:

您可以使用@JsonIgnore 注解忽略任何对象的序列化 示例代码应该是:

@Entity
public class A {

    private long id;

    @ManyToOne
    private B b;

    // ...
}

@Entity
public class B {

    private long id;
    private String str;
    private boolean bool;

    @OneToMany
    @JsonIgnore
    Set<A> aList;
    // ...
}

【讨论】:

    【解决方案2】:

    您可以尝试使用@JsonIgnoreProperties 忽略某些字段

    @Entity
    public class A {
    
        private long id;
    
        @ManyToOne
        private B b;
    
        // ...
    }
    
    @Entity
    public class B {
    
        private long id;
        private String str;
        private boolean bool;
    
        @OneToMany
        @JsonIgnoreProperties({"ignoreField1", "ignoreField2"})
        Set<A> aList;
        // ...
    }
    

    【讨论】:

      【解决方案3】:

      有很多方法可以做到这一点:

      1) 忽略属性:

      @Entity
      public class A {
      
          private long id;
      
          @JsonIgnoreProperties({"prop1", "prop2"})
          @ManyToOne
          private B b;
      }
      

      2) JsonIdentityInfoPropertyGenerator。需要id 属性。

      public class A {
         @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
         @JsonIdentityReference(alwaysAsId = true)
         public B b; 
      
         public long id;
      }
      

      3) JsonValue - 表示应该用于序列化整个实例的单个方法/字段。

      public class B {
      
          @JsonValue
          public long id;
      }
      

      4) 自定义序列化器:

      @Entity
      @JsonSerialize(using = ASerializer.class)
      public class A {
      
          private long id;
      
          @ManyToOne
          private B b;
      
          // ...
      }
      

      在这种情况下,您需要实现ASerializer

      这不是自定义序列化对象的最简单但灵活且细粒度的方式。

      参见this 示例。

      【讨论】:

      • 嗨@J-Alex,我有几个关于选项2和3的问题。选项1没有用,因为对象有很多属性(超过50个)。我确实在 B 类中使用了选项 2。在 B 类的类级别中使用了@JsonIdentityInfo,但这导致我在 A 类中想要的字段只是一个字段而不是嵌套对象。关于选项 3,如果我在 B 类的 id 字段上使用 @JsonValue,这是否意味着当我独立于 A 类序列化 B 类时,仍然会得到整个对象?还是在每种情况下都只是 id?
      • 我也尝试实现选项 4。我的 A 类中有一个Set&lt;Element&gt; mySet = ...,它们具有双向(onetomany(A 类)/manytoone(Element))关系。当我序列化 A 类时,我遇到了递归问题。有什么办法可以在我的 ASerializer 类中避免它?
      • @Yonetmen 在第三种情况下它会影响所有序列化方法,以及独立序列化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多