Spring Boot中如何获取Spring自身使用的自动配置ObjectMapper实例?
问题描述
在Spring Boot应用中,我通过如下方式自定义Jackson ObjectMapper:
@Configuration public class JacksonConfig { @Value("${app.dateFormat}") private String dateFormat; @Value("${app.dateFormat} ${app.timeFormat}") private String dateTimeFormat; @Bean public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> { builder.serializationInclusion(Include.NON_NULL); builder.simpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); builder.serializers(new LocalDateSerializer(DateTimeFormatter.ISO_OFFSET_DATE)); builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); }; } }
另有一个使用ObjectMapper的Bean:
@Autowired private ApplicationContext springContext; @Bean public ISEAClient createPubClient() { OkHttpClient client = new OkHttpClient(); return new HttpRestSEAClient("http://localhost:8081/sea/", client, springContext.getBean(ObjectMapper.class)); }
但ISEAClient Bean在JSON序列化时仍会包含null属性,似乎ObjectMapper Bean并未受到Jackson2ObjectMapperBuilderCustomizer的影响。请问如何获取Spring自身使用的同一个ObjectMapper实例?
解决方案
1. 直接注入ObjectMapper而非从ApplicationContext获取
把createPubClient Bean改成直接注入ObjectMapper,Spring会自动注入已经被Jackson2ObjectMapperBuilderCustomizer定制好的实例:
@Autowired private ObjectMapper objectMapper; @Bean public ISEAClient createPubClient() { OkHttpClient client = new OkHttpClient(); return new HttpRestSEAClient("http://localhost:8081/sea/", client, objectMapper); }
或者更推荐构造注入(符合Spring最佳实践):
private final ObjectMapper objectMapper; public YourConfigClass(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @Bean public ISEAClient createPubClient() { OkHttpClient client = new OkHttpClient(); return new HttpRestSEAClient("http://localhost:8081/sea/", client, objectMapper); }
2. 检查是否存在多个ObjectMapper Bean
如果应用中存在其他自定义的ObjectMapper Bean,Spring可能会注入未被定制的实例。可以通过两种方式确认:
- 启动应用时查看日志,搜索
ObjectMapper相关的Bean注册信息 - 在代码中调用
springContext.getBeansOfType(ObjectMapper.class),打印所有ObjectMapper实例,排查哪个是Spring默认的
3. 直接定制默认ObjectMapper Bean
如果上述方法无效,可以直接定义自己的ObjectMapper Bean,替代Spring默认实例:
@Configuration public class JacksonConfig { @Value("${app.dateFormat}") private String dateFormat; @Value("${app.dateFormat} ${app.timeFormat}") private String dateTimeFormat; @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(Include.NON_NULL); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")); JavaTimeModule timeModule = new JavaTimeModule(); timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_OFFSET_DATE)); timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); objectMapper.registerModule(timeModule); return objectMapper; } }
这种方式会让Spring直接使用你定义的ObjectMapper,确保所有依赖它的Bean都能拿到定制后的实例。
内容的提问来源于stack exchange,提问作者WestFarmer
相关产品推荐
相关产品推荐

