How do I have Multiple JsonView inheritance

2.4k Views Asked by At

I have a scenario in Java SpringBoot 1.5.7 where I have multiple classes and I want to be able to Apply different JsonViews to each through inheritance like.

 ClassA{

    @JsonView({SummaryView.class})
    public String name;

    @JsonView({DetailView.class})
    public String description;

    public interface SummaryView{}

    public interface DetailView extends SummaryView {}
 }

Class A is a property in Class B. ClassB should only be serialized to Json when the DetailView JsonView of ClassB is used.

 ClassB{

    @JsonView({SummaryView.class})
    private String name;

    @JsonView({DetailView.class})
    private String description;

    @JsonView({DetailView.class})
    private ClassA classA;

    public interface SummaryView{}

    public interface DetailView extends SummaryView, ClassA.SummaryView {}
 }

Class B is also a property in class C.

 ClassC{

    @JsonView({SummaryView.class})
    private String name;

    @JsonView({DetailView.class})
    private String description;

    @JsonView({DetailView.class})
    private ClassB classB;

    public interface SummaryView{}

    public interface DetailView extends SummaryView, ClassB.DetailView {}
 }

In my real life scenario I can have upto 5 levels of inheritance needed. In my rest controller I want to use different views. When I use ClassC.DetailView.class view the JsonView is just working with the immediate class ie ClassC and ClassB but ClassA properties are not included in the resulting Json. The result is:

{
  "name": "classC",
  "description": "Has submodel Class B",

  "classB": {
    "name": "classB",
    "description": "Has submodel ClassA",

    "classA": { }
  }
}

I have also tried to put the JsonView classes from the outer most class in the innermost class ie. Having @JsonView(ClassC.DetailView.class) in ClassA properties but it is also not working.

Me desired result is:

{
  "name": "classC",
  "description": "Has submodel Class B",

  "classB": {
    "name": "classB",
    "description": "Has submodel ClassA",

    "classA": {
      "name": "classA"
    }
  }
}

How do I get this working?

1

There are 1 best solutions below

0
On

I know the following is not an answer. However, I copied your class and view hierarchy. When I explicitly invoke Jackson's ObjectMapper with a given view, I get the desired result (using latest Jackson version, 2.9.3)

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;

public class TestJsonViewInheritence
{

    public static void main(String[] args) {
        try {
        ObjectMapper mapper = new ObjectMapper();
        mapper
          .enable(SerializationFeature.INDENT_OUTPUT)
          .writerWithView(ClassC.DetailView.class)
          .writeValue(System.out, new ClassC());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class ClassA
    {
        @JsonView({ SummaryView.class })
        public String name = "ClassA";

        @JsonView({ DetailView.class })
        public String description = "Has no submodel";

        public interface SummaryView {}

        public interface DetailView extends SummaryView {}
    }

    public static class ClassB
    {
        @JsonView({ SummaryView.class })
        private String name = "ClassB";

        @JsonView({ DetailView.class })
        private String description = "Has submodel ClassA";

        @JsonView({ DetailView.class })
        private ClassA classA = new ClassA();

        public interface SummaryView {}

        public interface DetailView extends SummaryView, ClassA.SummaryView {}
    }

    public static class ClassC
    {
        @JsonView({ SummaryView.class })
        private String name = "ClassC";

        @JsonView({ DetailView.class })
        private String description = "Has submodel ClassB";

        @JsonView({ DetailView.class })
        private ClassB classB = new ClassB();

        public interface SummaryView {}

        public interface DetailView extends SummaryView, ClassB.DetailView {}
    }
}

output:

{
  "name" : "ClassC",
  "description" : "Has submodel ClassB",
  "classB" : {
    "name" : "ClassB",
    "description" : "Has submodel ClassA",
    "classA" : {
      "name" : "ClassA"
    }
  }
}