Search code examples
javajacksonjackson-databindjson-view

Class and field level @JsonView annotation and Object Mapper


I have views and entity class as shown below:

class Views{
   class ViewOne{}
   class ViewTwo{}
}

class Test{

   @JsonView({Views.ViewOne.class})
   public int x;

   @JsonView({Views.ViewTwo.class})
   public int y;

   public int z;

   public int v;
}

My question is that do I need to have @JsonView({Views.ViewOne.class, Views.ViewTwo.class}) at class level so that I have non-annotated fields like z, v in the output response irrespective of View Class passed to Object Mapper?

I did try to look into different resources regarding the use of class level @JsonView annotation but I couldn't find any. Does it have any effect? If yes, pls do explain the same.


Solution

  • Do I need to have @JsonView({Views.ViewOne.class, Views.ViewTwo.class}) at class level so that I have non-annotated fields like z, v in the output response irrespective of view class passed to ObjectMapper?

    You won't need that when MapperFeature.DEFAULT_VIEW_INCLUSION is enabled in your ObjectMapper instance. This feature is enabled by default. May have you disabled it somehow?

    Here's a quote from the documentation:

    Feature that determines whether properties that have no view annotations are included in JSON serialization views (see @JsonView for more details on JSON Views). If enabled, non-annotated properties will be included; when disabled, they will be excluded.


    Example 1

    Let's consider the following Example class:

    @Data
    public class Example {
    
        private int a = 1;
    
        private int b = 2;
    
        private int c = 3;
    }
    

    And let's serialize an instance of Example as a JSON using:

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(new Foo());
    

    It will produce the following JSON:

    {"a":1,"b":2,"c":3}
    

    Example 2

    Now let's take the following views into account:

    public class Views {
    
        public static class Foo {}
    
        public static class Bar {}
    }
    

    And let's the apply the views to the fields of the Example class:

    @Data
    public class Example {
    
        @JsonView(Views.Foo.class)
        private int a = 1;
    
        @JsonView(Views.Bar.class)
        private int b = 2;
    
        private int c = 3;
    }
    

    And let's serialize an instance of Example using the Foo view:

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writerWithView(Views.Foo.class).writeValueAsString(new Example());
    

    It will produce the following JSON:

    {"a":1,"c":3}
    

    Now let's disable the default view inclusion an serialize it again:

    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
    String json = mapper.writerWithView(Views.Foo.class).writeValueAsString(new Example());
    

    It will produce the following JSON:

    {"a":1}
    

    Example 3

    Now let's use the following view configuration in the Example class:

    @Data
    @JsonView(Views.Foo.class)
    public static class Example {
    
        private int a = 1;
    
        @JsonView(Views.Bar.class)
        private int b = 2;
    
        private int c = 3;
    }
    

    And let's serialize an instance of Example using the Foo view:

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writerWithView(Views.Foo.class).writeValueAsString(new Example());
    

    It will produce the following JSON:

    {"a":1,"c":3}
    

    Now let's serialize an instance of Example using the Bar view:

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writerWithView(Views.Bar.class).writeValueAsString(new Example());
    

    It will produce the following JSON:

    {"b":2}