I'm building a REST API using a CRUD repository based on Spring Boot and Spring Data JPA.
I have a problem with JSON serialization. Many entities contain a relation and I want to limit the number of nested entities when retrieving data with get method.
This is an example of two entities that work as expected:
@Entity
@Table
public class Series {
private @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Integer id;
@Column(name = "publisher_id")
private @NotEmpty @NotNull Integer publisherId;
@Column(name = "title")
private @NotEmpty @NotNull String title;
@JsonManagedReference
@OneToMany(mappedBy = "series")
private List<Subseries> subseriesList;
public void addSubseries(Subseries subseries) {
subseriesList.add(subseries);
subseries.setSeries(this);
}
}
@Entity
@Table(name = "subseries")
public class Subseries {
private @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Integer id;
@Column(name = "series_id", insertable = false, updatable = false)
private @NotEmpty @NotNull Integer seriesId;
@Column(name = "title")
private @NotEmpty @NotNull String title;
@JsonBackReference
@ManyToOne
@JoinColumn(name = "series_id", foreignKey = @ForeignKey(name = "id"))
private @NotEmpty @NotNull Series series;
}
Both classes implement Serializable interface and have their getters and setters and empty constructor.
This is the output of get method for series/10:
{
"id": 10,
"publisherId": 100,
"title": "Title of the series",
"subseriesList": [
{
"id": 11,
"seriesId": 10,
"title": "Title of the first subseries"
},
{
"id": 12,
"seriesId": 10,
"title": "Title of the second subseries"
}
]
}
And this is the output for subseries/11:
{
"id": 11,
"seriesId": 10,
"title": "Title of the first subseries"
}
So far, everything is working as expected: I need the subseries for the selected series and that's what I get. The problem arises with this entity, that references Series:
@Entity
@Table(name = "publication")
@NoArgsConstructor
public class Publication {
private @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Integer id;
@Column(name = "publisher_id")
private Integer publisherId;
@Column(name = "series_id", insertable = false, updatable = false)
private Integer seriesId;
@Column(name = "subseries_id")
private Integer subseriesId;
@Column(name = "cover_title")
private @NotEmpty @NotNull String coverTitle;
@JsonManagedReference
@ManyToOne
@JoinColumn(name = "series_id", foreignKey = @ForeignKey(name = "id"))
private Series series;
// TODO: @ManyToOne reference for Subseries
}
This entity represents a book, which may belong to a series and possibly to a subseries of that series. I want to get the referenced series and subseries as nested data, but I don't want to get the nested data of the series. This is what I get:
{
"id": 56,
"publisherId": 100,
"seriesId": 10,
"subseriesId": 11,
"coverTitle": "Book title",
"series": {
"id": 10,
"publisherId": 100,
"title": "Title of the series",
"subseriesList": [
{
"id": 11,
"seriesId": 10,
"title": "Title of the first subseries"
},
{
"id": 12,
"seriesId": 10,
"title": "Title of the second subseries"
}
]
}
}
I don't need the full list of subseries (also, the second one has nothing to do with the selected publication) and I have no idea of how I could get rid of them for a publication while keeping them for a series. This is what I want:
{
"id": 56,
"publisherId": 100,
"seriesId": 10,
"subseriesId": 11,
"coverTitle": "Book title",
"series": {
"id": 10,
"publisherId": 100,
"title": "Title of the series"
}
}
This is just an example, but I have the same problem with many other entities in my project.
I had a similar problem here but the situation is different as it works with the main entity and not the nested ones.
I've been suggested to use separate POJOs for the REST service but that would make the code hard to maintain.
What I'm looking for is something like @JsonIgnore or @JsonManagedReference/@JsonBackReference that allows to keep the references when Series is the main entity and discard references when it is a nested entity. Another possible solution would be limiting the number of nested entities to one.
Is there any way to do that?