Spring Boot中为ObjectMapper添加自定义过滤器提供者的实现难题
解决Spring Boot中ObjectMapper被占用时添加自定义序列化过滤器的问题
我之前也碰到过类似的场景——依赖库占了默认的primary ObjectMapper没法改,还有一堆其他的ObjectMapper Bean搞事情,想加自定义序列化过滤器真是头大。这里分享几个靠谱的解决方案:
方案1:创建专属的过滤型ObjectMapper Bean
最稳妥的方式就是自己搞一个专门用来处理过滤序列化的ObjectMapper,用@Qualifier标记,避免和其他Bean混淆:
配置自定义ObjectMapper
@Configuration public class FilteredObjectMapperConfig { @Bean("filteredObjectMapper") public ObjectMapper filteredObjectMapper() { // 创建新的ObjectMapper实例,完全独立于默认Bean ObjectMapper mapper = new ObjectMapper(); // 配置你的自定义过滤器 FilterProvider filterProvider = new SimpleFilterProvider() .addFilter("sensitiveFieldFilter", SimpleBeanPropertyFilter.filterOutAllExcept("id", "username", "email")); mapper.setFilterProvider(filterProvider); // 对齐Spring Boot默认配置,避免序列化行为不一致 mapper.registerModule(new JavaTimeModule()); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return mapper; } }
使用时指定注入
在需要序列化的地方,用@Qualifier明确注入自己的过滤型ObjectMapper:
@Service public class UserService { private final ObjectMapper filteredObjectMapper; // 用@Qualifier指定注入我们自定义的Bean public UserService(@Qualifier("filteredObjectMapper") ObjectMapper filteredObjectMapper) { this.filteredObjectMapper = filteredObjectMapper; } public String serializeUser(User user) throws JsonProcessingException { // 用专属mapper序列化,自动过滤敏感字段 return filteredObjectMapper.writeValueAsString(user); } }
方案2:临时给ObjectWriter添加过滤器(局部生效)
如果只是某些特定场景需要过滤,不想单独搞一个Bean,可以在序列化时临时创建带过滤器的ObjectWriter,不管用哪个ObjectMapper都能生效:
先给POJO标记过滤器
// 给需要过滤的POJO加上@JsonFilter注解,指定过滤器名称 @JsonFilter("sensitiveFieldFilter") public class User { private Long id; private String username; private String email; private String password; // 敏感字段,需要过滤 private String phone; // 敏感字段,需要过滤 // getter、setter省略 }
序列化时临时配置过滤器
// 可以是默认的ObjectMapper,也可以是其他Bean注入的 @Autowired private ObjectMapper defaultObjectMapper; public String serializeFilteredUser(User user) throws JsonProcessingException { FilterProvider filterProvider = new SimpleFilterProvider() .addFilter("sensitiveFieldFilter", SimpleBeanPropertyFilter.filterOutAllExcept("id", "username", "email")); // 用ObjectWriter临时绑定过滤器,不影响原ObjectMapper的全局配置 return defaultObjectMapper.writer(filterProvider).writeValueAsString(user); }
方案3:给Web响应配置专属消息转换器(全局Web场景)
如果需要在所有Web接口的响应中自动过滤字段,可以自定义MappingJackson2HttpMessageConverter,用我们的过滤型ObjectMapper:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired @Qualifier("filteredObjectMapper") private ObjectMapper filteredObjectMapper; @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 创建自定义消息转换器 MappingJackson2HttpMessageConverter filteredConverter = new MappingJackson2HttpMessageConverter(); filteredConverter.setObjectMapper(filteredObjectMapper); // 把自定义转换器放在最前面,优先使用 converters.add(0, filteredConverter); } }
关键注意事项
- 绝对不要修改依赖库占用的
primary ObjectMapper,否则可能导致依赖库的功能异常(比如第三方SDK的序列化逻辑崩溃) - 自定义
ObjectMapper时尽量对齐Spring Boot的默认配置,避免出现日期格式、枚举序列化等不一致的问题 - 如果多个
ObjectMapperBean共存,注入时一定要用@Qualifier明确指定,避免Spring注入错误的实例
内容的提问来源于stack exchange,提问作者Arnab Gupta
相关产品推荐
相关产品推荐

