Autowiring in JsonDeserializer: SpringBeanAutowiringSupport vs HandlerInstantiator

前端 未结 3 1579
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-03 11:04

I have written a custom JsonDeserializer which contains an autowired service, as follows:

public class PersonDeserializer extends JsonDeserializ         


        
3条回答
  •  一生所求
    2020-12-03 12:06

    As suggested in this comment and found on this link you need to create custom HandlerInstantiator:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.stereotype.Component;
    
    import com.fasterxml.jackson.databind.DeserializationConfig;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.KeyDeserializer;
    import com.fasterxml.jackson.databind.SerializationConfig;
    import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
    import com.fasterxml.jackson.databind.cfg.MapperConfig;
    import com.fasterxml.jackson.databind.introspect.Annotated;
    import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
    import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
    
    @Component
    public class SpringBeanHandlerInstantiator extends HandlerInstantiator {
    
        private ApplicationContext applicationContext;
    
        @Autowired
        public SpringBeanHandlerInstantiator(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public JsonDeserializer deserializerInstance(DeserializationConfig config,
                Annotated annotated,
                Class deserClass) {
            try {
                return (JsonDeserializer) applicationContext.getBean(deserClass);
            } catch (Exception e) {
                // Return null and let the default behavior happen
            }
            return null;
        }
    
        @Override
        public KeyDeserializer keyDeserializerInstance(DeserializationConfig config,
                Annotated annotated,
                Class keyDeserClass) {
            try {
                return (KeyDeserializer) applicationContext.getBean(keyDeserClass);
            } catch (Exception e) {
                // Return null and let the default behavior happen
            }
            return null;
        }
    
        @Override
        public JsonSerializer serializerInstance(SerializationConfig config, Annotated annotated, Class serClass) {
            try {
                return (JsonSerializer) applicationContext.getBean(serClass);
            } catch (Exception e) {
                // Return null and let the default behavior happen
            }
            return null;
        }
    
        @Override
        public TypeResolverBuilder typeResolverBuilderInstance(MapperConfig config, Annotated annotated,
                Class builderClass) {
            try {
                return (TypeResolverBuilder) applicationContext.getBean(builderClass);
            } catch (Exception e) {
                // Return null and let the default behavior happen
            }
            return null;
        }
    
        @Override
        public TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated annotated, Class resolverClass) {
            try {
                return (TypeIdResolver) applicationContext.getBean(resolverClass);
            } catch (Exception e) {
                // Return null and let the default behavior happen
            }
            return null;
        }
    }
    

    Custom ObjectMapper:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
    
    
    public class CustomObjectMapper extends ObjectMapper {
        private static final long serialVersionUID = -8865944893878900100L;
    
        @Autowired
        ApplicationContext applicationContext;
    
        public JamaxObjectMapper() {
            // Problems serializing Hibernate lazily initialized collections?  Fix here.
    //        HibernateModule hm = new HibernateModule();
    //        hm.configure(com.fasterxml.jackson.module.hibernate.HibernateModule.Feature.FORCE_LAZY_LOADING, true);
    //        this.registerModule(hm);
    
            // Jackson confused by what to set or by extra properties?  Fix it.
            this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        }
    
        @Override
        @Autowired
        public Object setHandlerInstantiator(HandlerInstantiator hi) {
            return super.setHandlerInstantiator(hi);
        }
    }
    

    and register your custom ObjectMapper:

    
    
        
        
        
    
    

    At this moment you can use:

    @JsonDeserialize(contentUsing=PersonDeserializer.class)
    public void setPerson(Person person) {
        ...
    }
    

    ... and personService will not be null.

提交回复
热议问题