You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中能否配置两个MappingJackson2HttpMessageConverter Bean适配多API需求?

你的配置存在关键问题,直接注册两个MappingJackson2HttpMessageConverter无法实现预期效果

直接在WebMvcConfig里注册两个同类型的消息转换器,Spring MVC会把它们都加入转换器链,处理请求时会按顺序尝试匹配,无法精准区分哪些API用默认转换器、哪些用自定义转换器,最终可能出现所有请求都走第一个转换器的情况,达不到部分API保留null值的目的。

正确的实现思路及方案

方案一:用自定义注解+ControllerAdvice绑定特定转换器

这个方案最灵活,能精准控制哪些接口保留null值:

  1. 先定义一个标记注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface KeepNullFields {
}
  1. 创建ControllerAdvice,给带该注解的接口绑定自定义ObjectMapper
@RestControllerAdvice(annotations = KeepNullFields.class)
public class KeepNullResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {
    public KeepNullResponseBodyAdvice(@Qualifier("customObjectMapper") ObjectMapper customObjectMapper) {
        super(customObjectMapper);
    }
}
  1. 在需要保留null值的控制器或方法上添加注解
@RestController
@RequestMapping("/api/need-null")
@KeepNullFields
public class NeedNullController {
    @GetMapping("/info")
    public UserDto getUserInfo() {
        UserDto dto = new UserDto();
        dto.setUsername("张三");
        dto.setPhone(null); // 这个null会被保留
        return dto;
    }
}

方案二:通过RequestMappingHandlerAdapter针对特定接口配置转换器

如果需要更底层的控制,可以自定义RequestMappingHandlerAdapter,给特定接口绑定转换器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ObjectMapper defaultObjectMapper;
    @Autowired
    @Qualifier("customObjectMapper")
    private ObjectMapper customObjectMapper;

    // 注册默认转换器,处理大部分请求
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter defaultConverter = new MappingJackson2HttpMessageConverter(defaultObjectMapper);
        converters.add(defaultConverter);
    }

    // 给带@KeepNullFields注解的接口配置自定义转换器
    @Bean
    public RequestMappingHandlerAdapter keepNullRequestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
        MappingJackson2HttpMessageConverter customConverter = new MappingJackson2HttpMessageConverter(customObjectMapper);
        adapter.setMessageConverters(List.of(customConverter));
        // 设置只处理带@KeepNullFields注解的方法
        adapter.setRequestMappingHandlerMapping(new RequestMappingHandlerMapping() {
            @Override
            protected boolean isHandler(Class<?> beanType) {
                return beanType.isAnnotationPresent(KeepNullFields.class) || Arrays.stream(beanType.getMethods()).anyMatch(m -> m.isAnnotationPresent(KeepNullFields.class));
            }
        });
        return adapter;
    }
}

方案三:接口方法内手动使用自定义ObjectMapper

如果只是少数几个接口需要保留null值,也可以不用全局配置,直接在方法里手动序列化:

@RestController
@RequestMapping("/api/single")
public class SingleNeedNullController {
    @Autowired
    @Qualifier("customObjectMapper")
    private ObjectMapper customObjectMapper;

    @GetMapping("/detail")
    public ResponseEntity<String> getDetail() throws JsonProcessingException {
        OrderDto dto = new OrderDto();
        dto.setOrderNo("20240501001");
        dto.setDiscount(null);
        // 手动用自定义ObjectMapper序列化
        String json = customObjectMapper.writeValueAsString(dto);
        return ResponseEntity.ok(json);
    }
}

额外注意事项

  • 你的两个ObjectMapper Bean配置是没问题的,但要确保customObjectMapper的配置确实开启了保留null值(比如配置serializationInclusion(JsonInclude.Include.ALWAYS))
  • 不要直接把两个MappingJackson2HttpMessageConverter都加入全局转换器列表,否则Spring会按顺序匹配,无法区分接口

内容的提问来源于stack exchange,提问作者mohammed rabee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:17:42