skip to Main Content

I have a spring boot application with frontend and backend connected using apache HttpClient.
There are many bi-directional associations between the entities. For example:

    @NamedEntityGraphs(
    {
        @NamedEntityGraph(name = "graph.ApplicationUserProcesses",
            attributeNodes ={
                @NamedAttributeNode(value = "processes", subgraph = "processes"),
                @NamedAttributeNode(value = "roles")
            },
            subgraphs = @NamedSubgraph(name = "processes",
                attributeNodes = {
                    @NamedAttributeNode("applicationUsers")
                })
        )
    }
)

public class ApplicationUser implements Serializable {

    @Id
    private UUID id;

    @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable( name = "app_user_role",
        joinColumns = @JoinColumn(name = "app_user_id"),
        inverseJoinColumns = @JoinColumn(name = "app_user_role_id"))
    private Set<Role> roles = new HashSet<>();

    @JsonIgnore
    @ManyToMany(mappedBy = "applicationUsers", fetch = FetchType.LAZY)
    private Set<Process> processes = new HashSet<>();
}





public class Process  implements Serializable {

    @Id
    private UUID id;
    
    @ManyToMany( fetch = FetchType.LAZY)
    @JoinTable( name = "membership",
        joinColumns = @JoinColumn(name = "process_id"),
        inverseJoinColumns = @JoinColumn(name = "user_id"))
    private Set<ApplicationUser> applicationUsers = new HashSet<>();
}

The process and applicationUser entities have bi-directional association as shown above. The issue is that when the backend returns applicationUser object, there is continuous nesting of objects in the json (as shown below) which is not needed. How to make the json API from the backend stop nesting.

    applicationUser:{
    processes:[{
        process1:{
            applicationUser:{
                processes:[{
                    process1:{
                    
                    }
                }]
            }
        }
    }]
}

Is there anyway to prevent the nesting of objects in the json and maintain clean API.

2

Answers


  1. You need to use Jackson’s @JsonManagedReference and @JsonBackReference annotation to avoid that.

    On parent class where you want to allow child to be included in JSON add @JsonManagedReference annotation.

    public class ApplicationUser implements Serializable {
    
        @Id
        private UUID id;
    
        @JsonManagedReference
        @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
        @JoinTable( name = "app_user_role",
            joinColumns = @JoinColumn(name = "app_user_id"),
            inverseJoinColumns = @JoinColumn(name = "app_user_role_id"))
        private Set<Role> roles = new HashSet<>();
    
        @JsonManagedReference
        @ManyToMany(mappedBy = "applicationUsers", fetch = FetchType.LAZY)
        private Set<Process> processes = new HashSet<>();
    
    }
    

    On child class where you don’t want to include parent in JSON add @JsonBackReference.

    public class Process  implements Serializable {
    
        @Id
        private UUID id;
        
        @JsonBackReference
        @ManyToMany( fetch = FetchType.LAZY)
        @JoinTable( name = "membership",
            joinColumns = @JoinColumn(name = "process_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id"))
        private Set<ApplicationUser> applicationUsers = new HashSet<>();
    
    }
    

    You should not expose the entity to API instead use DTO/VO which are POJO classes that holds the values. Try Using different POJO classes based on how you want to expose your entity relationship. Or try to avoid bidirectional relationship in entity as generally not required as you will always get child from parent or vice versa.

    Login or Signup to reply.
  2. To prevent nesting of JSON objects in your API, consider using the @JsonBackReference and @JsonManagedReference annotations to manage bi-directional relationships, implement Data Transfer Objects (DTOs) to explicitly control the serialized structure, or utilize Jackson’s customized serialization views to selectively serialize properties based on the context. These approaches allow you to break infinite recursion and tailor the JSON output to meet your API’s requirements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search