Eliminate circular JSON in Java Spring Many to Many Relationship

Using the @JsonIgnoreProperties annotation is another alternative:

@Entity
public class Student extends AbstractUser {
    @ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class)
    @JoinTable(name = "GROUPS_STUDENTS",
            joinColumns = { @JoinColumn(name = "student_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") })
    @JsonIgnoreProperties("students")
    private List<Group> groups = new ArrayList<Group>();
}

@Entity
public class Group implements Item, Serializable {
    @ManyToMany(mappedBy = "groups", targetEntity = Student.class)
    @JsonIgnoreProperties("groups")
    private List<Student> students;
}

Find comparison between @JsonManagedReference+@JsonBackReference, @JsonIdentityInfo and @JsonIgnoreProperties here: http://springquay.blogspot.com/2016/01/new-approach-to-solve-json-recursive.html


To solve jackson infinite recursion you can use @JsonManagedReference, @JsonBackReference.

@JsonManagedReference is the forward part of reference – the one that gets serialized normally.

@JsonBackReference is the back part of reference – it will be omitted from serialization.

Find more details here: http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

public class Student extends AbstractUser {
    @ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class)
    @JoinTable(name = "GROUPS_STUDENTS",
            joinColumns = { @JoinColumn(name = "student_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") })
    @JsonManagedReference
    private List<Group> groups = new ArrayList<Group>();
}

public class Group implements Item, Serializable {
    @ManyToMany(mappedBy = "groups", targetEntity = Student.class)
    @JsonBackReference
    private List<Student> students;
}

I've solved it. I've made a custom serializer. So in Group I'll serialize the students by setting a custom annotation @JsonSerialize(using = CustomStudentSerializer.class)

CustomStudentSerializer

public class CustomStudentSerializer extends StdSerializer<List<Student>> {

    public CustomStudentSerializer() {
        this(null);
    }

    public CustomStudentSerializer(Class<List<Student>> t) {
        super(t);
    }

    @Override
    public void serialize(
            List<Student> students,
            JsonGenerator generator,
            SerializerProvider provider)
            throws IOException, JsonProcessingException {

        List<Student> studs = new ArrayList<>();
        for (Student s : students) {
            s.setGroups(null);
            studs.add(s);
        }
        generator.writeObject(studs);
    }
}

Did the same for the groups. I've just removed the students/group component when the relationship is already nested. And now it works just fine.

Took me a while to figure this out but I posted here because it may help someone else too.