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

Spring MVC(非Spring Boot)环境下Jackson转换器的正确配置:支持无空值JSON、合法字符串JSON与纯文本响应

解决方案:让消息转换器各司其职

核心问题出在StringHttpMessageConverter和MappingJackson2HttpMessageConverter的职责重叠——当你把StringHttpMessageConverter放在前面时,它会处理所有String类型的返回值,不管这个返回值应该是纯文本还是JSON格式的字符串。我们需要给每个转换器明确划分处理范围,让它们只负责对应的MediaType。

步骤1:配置专属的字符串转换器(仅处理纯文本)

创建一个只支持text/plain类型的StringHttpMessageConverter,这样它不会抢占JSON格式的字符串处理:

@Bean
public StringHttpMessageConverter stringHttpMessageConverter() {
    StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
    // 仅让该转换器处理text/plain类型的响应
    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN));
    return converter;
}

步骤2:保持JSON转换器的配置(去除null字段)

你的原有JSON转换器配置可以保留,但建议加上UTF-8的MediaType以避免编码问题:

@Bean 
public MappingJackson2HttpMessageConverter jsonConverter() { 
    List<MediaType> supportedMediaTypes = new ArrayList<>(); 
    supportedMediaTypes.add(MediaType.APPLICATION_JSON);
    supportedMediaTypes.add(new MediaType("application", "json", StandardCharsets.UTF_8)); // 支持UTF-8编码的JSON

    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); 
    builder.serializationInclusion(JsonInclude.Include.NON_NULL); 
    builder.timeZone(TimeZone.getTimeZone(timeZone)); 

    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(builder.build()); 
    jsonConverter.setSupportedMediaTypes(supportedMediaTypes); 
    return jsonConverter; 
}

步骤3:按顺序注册转换器

在configureMessageConverters中按顺序添加两个转换器——先纯文本转换器,再JSON转换器:

@Override 
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    converters.add(stringHttpMessageConverter()); 
    converters.add(jsonConverter()); 
}

步骤4:明确端点的响应类型

为了让Spring能正确匹配转换器,建议给每个端点明确指定produces属性:

  • 纯文本端点:指定produces = MediaType.TEXT_PLAIN_VALUE
    @RequestMapping(value = "/plain-text", produces = MediaType.TEXT_PLAIN_VALUE)
    @ResponseBody
    public String getPlainText() {
        return "Hello Plain Text"; // 直接返回不带引号的纯文本
    }
    
  • JSON字符串端点:指定produces = MediaType.APPLICATION_JSON_VALUE
    @RequestMapping(value = "/json-string", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public String getJsonString() {
        return "Hello JSON String"; // 会被Jackson序列化为带引号的JSON:"Hello JSON String"
    }
    
  • POJO转JSON端点:同样指定produces = MediaType.APPLICATION_JSON_VALUE
    @RequestMapping(value = "/pojo-json", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public User getUser() {
        User user = new User();
        user.setName("Alice");
        user.setAge(null); // null字段会被自动移除
        return user;
    }
    

原理说明

Spring在处理响应时,会根据端点的produces属性和返回值类型,从注册的转换器中选择最匹配的那个:

  • 当响应类型是text/plain时,StringHttpMessageConverter会处理,直接返回原始字符串;
  • 当响应类型是application/json时,不管返回值是POJO还是String,MappingJackson2HttpMessageConverter都会处理:POJO会被序列化为去除null字段的JSON,String会被序列化为带双引号的合法JSON字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 21:52:29