在JsonDeserializer中自动assembly:SpringBeanAutowiringSupport与HandlerInstantiator
我编写了一个包含自动服务的自定义JsonDeserializer
,如下所示:
public class PersonDeserializer extends JsonDeserializer { @Autowired PersonService personService; @Override public Person deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { // deserialization occurs here which makes use of personService return person; } }
当我第一次使用这个解串器时,我得到了NPE,因为personService没有被自动assembly。 通过查看其他SO答案(特别是这一个 ),似乎有两种方法可以使自动assembly工作。
选项1是在自定义反序列化器的构造函数中使用SpringBeanAutowiringSupport
:
public PersonDeserializer() { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); }
选项2是使用HandlerInstantiator
并将其注册到我的ObjectMapper
bean:
@Component public class SpringBeanHandlerInstantiator extends HandlerInstantiator { @Autowired private ApplicationContext applicationContext; @Override public JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class<? extends JsonDeserializer> deserClass) { try { return (JsonDeserializer) applicationContext.getBean(deserClass); } catch (Exception e) { // Return null and let the default behavior happen return null; } } } @Configuration public class JacksonConfiguration { @Autowired SpringBeanHandlerInstantiator springBeanHandlerInstantiator; @Bean public ObjectMapper objectMapper() { Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean(); jackson2ObjectMapperFactoryBean.afterPropertiesSet(); ObjectMapper objectMapper = jackson2ObjectMapperFactoryBean.getObject(); // add the custom handler instantiator objectMapper.setHandlerInstantiator(springBeanHandlerInstantiator); return objectMapper; } }
我尝试了两种选择,但它们同样有效。 显然,选项1更容易,因为它只有三行代码,但我的问题是:与HandlerInstantiator
方法相比,使用SpringBeanAutowiringSupport
有什么缺点吗? 我的应用程序将每分钟反序列化数百个对象,如果这有任何区别的话。
任何建议/反馈表示赞赏。
添加到Amir Jamak的答案中,您不必创建自定义HandlerInstantiator,因为Spring已经具有SpringHandlerInstantiator。
你需要做的是在Spring配置中将它连接到Jackson2ObjectMapperBuilder。
@Bean public HandlerInstantiator handlerInstantiator(ApplicationContext applicationContext) { return new SpringHandlerInstantiator(applicationContext.getAutowireCapableBeanFactory()); } @Bean public Jackson2ObjectMapperBuilder objectMapperBuilder(HandlerInstantiator handlerInstantiator) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.handlerInstantiator(handlerInstantiator); return builder; }
正如在此评论中所建议的那样,您需要创建自定义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; } }
自定义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); } }
并注册您的自定义ObjectMapper:
此时你可以使用:
@JsonDeserialize(contentUsing=PersonDeserializer.class) public void setPerson(Person person) { ... }
…而personService不会为null。
使用弹簧靴清理上述答案,
@Bean public HandlerInstantiator handlerInstantiator(ApplicationContext context) { return new SpringHandlerInstantiator(context.getAutowireCapableBeanFactory()); } @Bean public ObjectMapper objectMapper(HandlerInstantiator handlerInstantiator) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.handlerInstantiator(handlerInstantiator); return builder.build(); }