1

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.

Yug Singh
  • 3,112
  • 5
  • 27
  • 52

1 Answers1

4

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}
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • Thanks for the answer. I also read about it and found out that by-default it's enabled and so all properties not explicitly marked as being part of a view, are serialized. But then what's the use of **class-level** `@JsonView` annotation(I mean `@JsonView` written above class Name). I was under the impression that I am getting non-annotated fields in my response due to that. But now I have removed it as and it's still working because of DEFAULT_VIEW_INCLUSION enabled by-default.So that's not the use case for class-level `@JsonView` annotation. Could you pls let me know ur thoughts on this? – Yug Singh Mar 27 '19 at 08:49
  • 2
    @YugSingh Since Jackson 2.9, `@JsonView` can be used on classes (see the [release notes](https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9)) to specify the _default view_ to use on non-annotated properties. This behavior can be overridden by `@JsonView` at property-level. Also see this [issue in GitHub](https://github.com/FasterXML/jackson-databind/issues/507), which requested this feature. – cassiomolin Mar 27 '19 at 09:15
  • Thanks again for the above info. I did refer to the release notes as well as the issue in github. What I understood is class-level JsonView annotations used to specify the default view for non-annotated attr. which means when we specify the default view class only then we will get the non-annotated attributes along with all the annotated attributes(if any with that particular default view class). Pls let me know If my understanding is correct. – Yug Singh Mar 27 '19 at 09:34
  • 1
    I just tried it. First I got **DEFAULT_VIEW_INCLUSION** disabled. After that I have class-level @JsonView annotations. Now when I am getting the response I can't see the non-annotated attributes at all. If I enable DEFAULT_VIEW_INCLUSION then it works properly. It looks like class-level jsonview has no effect. – Yug Singh Mar 27 '19 at 09:36
  • @YugSingh I've added some examples to my answer. Hope it clarifies the `@JsonView` usage. – cassiomolin Mar 27 '19 at 11:32