SpringBoot 1.5.10+Jackson2接收非Unicode的REST POST请求问题
在Spring Boot 1.5.10中让Jackson2支持非Unicode编码的JSON请求
核心问题
Spring Boot 1.5.10里的AbstractJackson2HttpMessageConverter默认直接将请求的InputStream传给Jackson解析,没有根据请求头Content-Type中指定的编码创建InputStreamReader,导致非UTF-8编码的JSON请求里的非ASCII字符解析失败。即便设置server.servlet.encoding.force-request=false关闭强制UTF-8,也无法解决这个问题——因为底层根本没读取请求头里的编码信息。
可行解决方案
方案一:自定义MappingJackson2HttpMessageConverter并替换默认实现
这是最稳妥的方式,不会有类路径冲突风险:
- 自定义转换器类
继承MappingJackson2HttpMessageConverter,重写read方法,根据请求头的编码创建InputStreamReader后再交给Jackson解析:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.lang.reflect.Type; public class EncodingAwareJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter { public EncodingAwareJackson2HttpMessageConverter(ObjectMapper objectMapper) { super(objectMapper); } @Override public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { // 从请求头获取编码,默认用UTF-8 Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType()); try (InputStreamReader reader = new InputStreamReader(inputMessage.getBody(), charset)) { return getObjectMapper().readValue(reader, getJavaType(type, contextClass)); } } private Charset getContentTypeCharset(org.springframework.http.MediaType contentType) { if (contentType != null && contentType.getCharset() != null) { return contentType.getCharset(); } return StandardCharsets.UTF_8; } }
- 配置替换默认转换器
创建一个WebMvcConfigurerAdapter的子类,覆盖configureMessageConverters方法,移除默认的Jackson转换器,添加自定义的:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.util.List; @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { private final ObjectMapper objectMapper; // 注入Spring默认的ObjectMapper,保证原有配置生效 public WebMvcConfig(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 移除默认的MappingJackson2HttpMessageConverter converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); // 添加自定义的转换器 converters.add(new EncodingAwareJackson2HttpMessageConverter(objectMapper)); // 保留其他默认转换器(比如StringHttpMessageConverter等) super.configureMessageConverters(converters); } }
方案二:类路径替换AbstractJackson2HttpMessageConverter(不推荐)
直接替换Spring的AbstractJackson2HttpMessageConverter类到类路径,但这种方式风险极高:
- Fat jar或war打包时,类加载顺序可能导致自定义类不生效,或者和Spring原有类冲突
- 后续Spring版本升级(哪怕是小版本)都可能导致兼容性问题
- 排查问题时很难定位到类替换的影响
所以除非万不得已,不建议使用这种方式。
验证
配置完成后,发送带有指定编码的JSON请求(比如Content-Type: application/json;charset=GBK),Jackson就能正确解析其中的非ASCII字符了。
内容的提问来源于stack exchange,提问作者aalku
相关产品推荐
相关产品推荐

