javaspringserializationjacksonjson-view

How to Apply @JsonView only for children of a Object with Spring RestController - serialization?


I have this case:

public class Project{

    private long id;

    private List<User> users;

    // other properties and getter setter etc
}

public class User{

   @JsonView(MinimalUser.class) 
   private long id;

   @JsonView(MinimalUser.class)
   private String name;

   private ComplexObject anything;

}

Now The RestMethod:


    @JsonView(MinimalUser.class)
    @GetMapping("/client/{id}")
    public List<Project> findProjectsByClientId(@PathVariable long id) {
        return projectService.findProjectsByClientId(id);
    }

Here I just want a project initialized with the minimal Users objects, but Nothing will be initialized, since there is no "MinimalUser.class" JsonView in my Project, hence it is not initialized.

I don't want to put the @JsonView Annotation, to all my variables in the Project, because this would be overkill.

How can I tell the Controller to only Apply the @JsonView-Filtering/Serialization to the User(child) of Project?

Because this call just works fine (I get only the required fields):


    @JsonView(MinimalUser.class)
    @GetMapping("/minimal")
    public List<User> findAllUsers() {
        return userService.findAllUsers();
    }


Solution

  • If you extend MinimalUser view and apply this new view to entire Project, you can get the following results:

    public class MinimalProject extends MinimalUser {}
    public class DetailedProject extends MinimalProject {}
    
    // apply view to entire class
    @JsonView(MinimalProject.class)
    public class Project {
        // keep existing fields as is
    
        // limit view for project
        @JsonView(DetailedProject.class)
        private String details;
    }
    
    // test
    ObjectMapper mapper = new ObjectMapper().disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
    
    User u = new User();
    u.setId(1);
    u.setName("John Doe");
    u.setEmail("john@doe.com");
    u.setDetails("some details");
    
    System.out.println("user default view: " + mapper.writeValueAsString(u));
    
    System.out.println("user minimal view: " + mapper.writerWithView(MinimalUser.class).writeValueAsString(u));
    
    Project p = new Project();
    
    p.setId(1000);
    p.setName("MegaProject");
    p.setUsers(Arrays.asList(u));
    p.setDetails("Project details: worth $1M");
    
    System.out.println("project default view: " + mapper.writeValueAsString(p));
    
    System.out.println("project minimal view: " + mapper.writerWithView(MinimalProject.class).writeValueAsString(p));
    

    output:

    user default view: {"id":1,"name":"John Doe","details":"some details","email":"john@doe.com"}
    user minimal view: {"id":1,"name":"John Doe"}
    project default view: {"id":1000,"users":[{"id":1,"name":"John Doe","details":"some details","email":"john@doe.com"}],"name":"MegaProject","details":"Project details: worth $1M"}
    project minimal view: {"id":1000,"users":[{"id":1,"name":"John Doe"}],"name":"MegaProject"}