Jackson - custom serializer that overrides only specific fields

后端 未结 5 1586
灰色年华
灰色年华 2020-12-09 10:01

I know how to use a custom serializer in Jackson (by extending JsonSerializer), but I want the default serializer to work for all fields, except for just 1 fiel

5条回答
  •  猫巷女王i
    2020-12-09 10:42

    with the help of @JsonView we can decide fields of model classes to serialize which satisfy the minimal criteria ( we have to define the criteria) like we can have one core class with 10 properties but only 5 properties can be serialize which are needful for client only

    Define our Views by simply creating following class:

    public class Views
    {
        static class Android{};
        static class IOS{};
        static class Web{};
    }
    

    Annotated model class with views:

    public class Demo 
    {
        public Demo() 
        {
        }
    
    @JsonView(Views.IOS.class)
    private String iosField;
    
    @JsonView(Views.Android.class)
    private String androidField;
    
    @JsonView(Views.Web.class)
    private String webField;
    
     // getters/setters
    ...
    ..
    }
    

    Now we have to write custom json converter by simply extending HttpMessageConverter class from spring as:

        public class CustomJacksonConverter implements HttpMessageConverter 
        {
        public CustomJacksonConverter() 
            {
                super();
            //this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.ClientView.class));
            this.delegate.getObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
            this.delegate.getObjectMapper().setSerializationInclusion(Include.NON_NULL);
    
        }
    
        // a real message converter that will respond to methods and do the actual work
        private MappingJackson2HttpMessageConverter delegate = new MappingJackson2HttpMessageConverter();
    
        @Override
        public boolean canRead(Class clazz, MediaType mediaType) {
            return delegate.canRead(clazz, mediaType);
        }
    
        @Override
        public boolean canWrite(Class clazz, MediaType mediaType) {
            return delegate.canWrite(clazz, mediaType);
        }
    
        @Override
        public List getSupportedMediaTypes() {
            return delegate.getSupportedMediaTypes();
        }
    
        @Override
        public Object read(Class clazz,
                HttpInputMessage inputMessage) throws IOException,
                HttpMessageNotReadableException {
            return delegate.read(clazz, inputMessage);
        }
    
        @Override
        public void write(Object obj, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException 
        {
            synchronized(this) 
            {
                String userAgent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("userAgent");
                if ( userAgent != null ) 
                {
                    switch (userAgent) 
                    {
                    case "IOS" :
                        this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.IOS.class));
                        break;
                    case "Android" :
                        this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.Android.class));
                        break;
                    case "Web" :
                        this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( Views.Web.class));
                        break;
                    default:
                        this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
                        break;
                    }
                }
                else
                {
                    // reset to default view
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
                }
                delegate.write(obj, contentType, outputMessage);
            }
        }
    
    }
    
    
    

    Now there is need to tell spring to use this custom json convert by simply putting this in dispatcher-servlet.xml

    
            
                
                
            
        
    

    That's how you will able to decide which fields to get serialize.

    Thanx

    提交回复
    热议问题