I'm using Jackson to serialize my JPA model into JSON.
I have the following classes:
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
}
and
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
}
I'm using the POJO mapping to serialize from model to JSON. When I serialize a Parent object I get the following JSON:
{
"id": 1,
"name": "John Doe",
"children": [
{
"id": 1,
"name": "child1"
},{
"id": 2,
"name": "child2"
}
]
}
But when I serialize a Child I get the following JSON:
{
"id": 1,
"name": "child1"
}
The reference to the parent is missing. Is there a way to solve this?
I think you have to choose between the @JsonIdentityInfo
and the @JsonBackReference
/ @JsonManagedReference
.
I would go with : @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id")
on your entities, removes @JsonBackReference
/ @JsonManagedReference
pairs.
And add @JsonIgnore
on the fields you want to exclude.
You can use JsonManagedReference / JsonBackReference and at the same time use JsonIdentityInfo to complement bidirectional relationships.
In question Class:
// 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<>();
In answer Class: // bi-directional many-to-one association to Question
@JsonBackReference
@ManyToOne
@JoinColumn(name = "questionId", referencedColumnName="id", foreignKey = @ForeignKey(name = "fk_answer_question"))
private Question question;
If you need parent reference in child object, remove Managed / Back Reference, this works fine for me.
The problem is that use of managed/back references requires that direction of traversal is always from parent to child (that is, using managed reference first). This is a limitation for these annotations.
As the other answer suggests, use of Object Ids is the more flexible alternative that could perhaps work.
One other option that could perhaps work would be to use JSON Views or JSON Filter to conditionally include/exclude parent reference, if you can separate cases. This could get messy.
@JsonIgnoreProperties({"excludedPropertyName"})
can do the job.
@Entity
public class Parent {
@JsonIgnoreProperties({"parent"})
@OneToMany(mappedBy = "parent")
private List<Child> children;
// ...
}
@Entity
public class Child {
@JsonIgnoreProperties({"children"})
@ManyToOne
private Parent parent;
// ...
}
You can use @JsonBackReference/@JsonManagedReference and add this method to child
@JsonProperty
public Long getParentId() {
return parent == null ? null : parent.getId();
}
Result will be:
{
"id": 1,
"name": "child1",
"parentId": 1
}
I hope this helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With