使用jackson将双向JPA实体序列化为JSON

时间:2014-03-24 16:37:36

标签: java json hibernate jpa jackson

我正在使用Jackson将我的JPA模型序列化为JSON。

我有以下课程:

import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
import java.util.Set;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
@Entity
public class Parent {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;

  @JsonManagedReference
  @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  private Set<Child> children;

  //Getters and setters
}

import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
@Entity
public class Child {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;

  @JsonBackReference
  @ManyToOne
  @JoinColumn(name = "parentId")
  private Parent parent;

  //Getters and setters
}

我正在使用POJO映射从模型序列化为JSON。当我序列化一个Parent对象时,我得到以下JSON:

{
  "id": 1,
  "name": "John Doe",
  "children": [
    {
      "id": 1,
      "name": "child1"
    },{
      "id": 2,
      "name": "child2"
    }
  ]
}

但是当我序列化一个Child时,我得到以下JSON:

{
  "id": 1,
  "name": "child1"
}

缺少对父级的引用。 有办法解决这个问题吗?

5 个答案:

答案 0 :(得分:28)

我认为你必须在@JsonIdentityInfo和@JsonBackReference / @JsonManagedReference之间进行选择。

我会在你的实体上使用:@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property =&#34; id&#34;),删除@JsonBackReference / @JsonManagedReference对。

在要排除的字段上添加@JsonIgnore。

答案 1 :(得分:5)

您可以使用JsonManagedReference / JsonBackReference,同时使用JsonIdentityInfo来补充双向关系。

问题类:

// bi-directional one-to-many association to Answer (Question is owner)
@JsonManagedReference
@OneToMany(mappedBy = "question", cascade = CascadeType.ALL)
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@QuestionAnswers")
private Set<Answer> answers = new HashSet<>();

回答课程: //与问题

的双向多对一关联
@JsonBackReference
@ManyToOne
@JoinColumn(name = "questionId", referencedColumnName="id", foreignKey = @ForeignKey(name = "fk_answer_question"))
private Question question;

如果您需要在子对象中使用父引用,请删除Managed / Back Reference,这对我来说很好。

答案 2 :(得分:3)

问题是使用托管/反向引用要求遍历的方向始终是从父级到子级(即,首先使用托管引用)。这是对这些注释的限制。

正如另一个答案所暗示的那样,使用Object Ids是一种更灵活的替代方案,可能有效。

另一个可能有用的选项是使用JSON视图或JSON过滤器有条件地包含/排除父引用,如果可以分离案例。这可能会变得混乱。

答案 3 :(得分:2)

您可以使用@ JsonBackReference / @ JsonManagedReference并将此方法添加到子

@JsonProperty
public Long getParentId() {
    return parent == null ? null : parent.getId();
}

结果将是:

{
  "id": 1,
  "name": "child1",
  "parentId": 1
}

我希望这有助于某人。

答案 4 :(得分:0)

@JsonIgnoreProperties({"excludedPropertyName"})可以胜任。

@Entity
public class Parent {

    @JsonIgnoreProperties({"parent"})
    @OneToMany(mappedBy = "parent")
    private List<Child> children; 

    // ...
}
@Entity
public class Child {

    @JsonIgnoreProperties({"children"})
    @ManyToOne
    private Parent parent;

    // ...
}