Combine Jackson @JsonView and @JsonProperty

前端 未结 1 574
独厮守ぢ
独厮守ぢ 2021-01-21 16:32

Is there a way to not only view/hide fields by using different classes in @JsonView but also define different names (like with @JsonProperty) depending on the view used for each

1条回答
  •  别那么骄傲
    2021-01-21 16:37

    My solution involves Jackson Mixin feature.
    I used the same view class to place the different @jsonProperty annotations. This is more convinient than a seperate class, however, now you cannot use inheritence of views. If you need this, you will have to create seperate classes that hold the @jsonProperty annotations and change the mixin modules accordingly.

    Here is the object to be serialized:

    public class Bean
    {
        @JsonView({Views.Public.class, Views.Internal.class})
        public String name;
    
        @JsonView(Views.Internal.class)
        public String ssn;
    }
    

    The views with the json property annotations

    public class Views
    {
        public static class Public {
            @JsonProperty("public_name")
            public String name;
        }
    
        public static class Internal {
            @JsonProperty("internal_name")
            public String name;
        }
    }
    

    The mixin modules, required by Jackson:

    @SuppressWarnings("serial")
    public class PublicModule extends SimpleModule
    {
        public PublicModule() {
            super("PublicModule");
        }
    
        @Override
        public void setupModule(SetupContext context)
        {
            context.setMixInAnnotations(Bean.class, Views.Public.class);
        }
    }
    
    @SuppressWarnings("serial")
    public class InternalModule extends SimpleModule
    {
        public InternalModule() {
            super("InternalModule");
        }
    
        @Override
        public void setupModule(SetupContext context)
        {
            context.setMixInAnnotations(Bean.class, Views.Internal.class);
        }
    }
    

    test method:

    public static void main(String[] args)
    {
        Bean bean = new Bean();
        bean.name = "my name";
        bean.ssn = "123-456-789";
    
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(args[0] + ": ");
        try {
            if (args[0].equals("public")) {
                mapper.registerModule(new PublicModule());
                mapper.writerWithView(Views.Public.class).writeValue(System.out, bean);
            } else {
                mapper.registerModule(new InternalModule());
                mapper.writerWithView(Views.Internal.class).writeValue(System.out, bean);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    output with two separate invocations:

    public: 
    {"public_name":"my name"}
    internal: 
    {"ssn":"123-456-789","internal_name":"my name"}
    

    0 讨论(0)
提交回复
热议问题