Spring Boot REST接口JsonMappingException异常排查求助
问题分析
从异常栈可以明确看出:系统在Ubuntu Java17 Docker环境中,错误地使用了Jackson的XML生成器(ToXmlGenerator)处理响应,而非JSON生成器。XML的标签命名规范不允许以数字开头(你的Map key是627228f554e7655db21f2859,首字符为数字),因此触发了XMLStreamException。本地Mac环境正常是因为默认使用了JSON转换器,JSON对键名的开头字符没有限制。
解决方案
针对这个环境差异导致的转换器选择问题,可从以下几个方向解决:
1. 强制接口返回JSON格式
在Controller的接口方法上显式指定produces属性,强制Spring Boot使用JSON转换器处理响应,忽略请求头的Accept配置:
@GetMapping(value = "/your-api-path", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<TestModel> handleRequest() { // 业务逻辑 TestModel model = buildTestModel(); return ResponseEntity.ok(model); }
2. 调整消息转换器优先级(保留XML支持的场景)
如果系统需要同时兼容JSON和XML响应,可调整转换器顺序,让JSON转换器优先;或配置XML转换器兼容非标准标签名:
方案A:提升JSON转换器优先级
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 找到JSON转换器并移至列表首位 for (int i = 0; i < converters.size(); i++) { if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) { MappingJackson2HttpMessageConverter jsonConverter = (MappingJackson2HttpMessageConverter) converters.remove(i); converters.add(0, jsonConverter); break; } } } }
方案B:配置XML转换器兼容数字开头的键名
通过自定义XmlMapper,允许生成非XML标准的标签名,或对Map的key进行转义(比如添加前缀):
@Bean public XmlMapper xmlMapper() { XmlMapper xmlMapper = new XmlMapper(); // 开启XML 1.1支持,允许更多字符作为标签开头 xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_1_1, true); // 或自定义Map序列化,给数字开头的key加前缀 xmlMapper.addMixIn(Map.class, MapXmlMixin.class); return xmlMapper; } // 定义Map的XML序列化Mixin public static abstract class MapXmlMixin { @JsonAnySetter public void setEntry(String key, Object value) {} @JsonAnyGetter @JsonSerialize(using = SafeMapKeySerializer.class) public abstract Map<String, Object> getEntries(); } // 自定义序列化器,处理数字开头的key public static class SafeMapKeySerializer extends JsonSerializer<Map<String, Object>> { @Override public void serialize(Map<String, Object> value, JsonGenerator gen, SerializerProvider serializers) throws IOException { ToXmlGenerator xmlGen = (ToXmlGenerator) gen; for (Map.Entry<String, Object> entry : value.entrySet()) { String safeKey = entry.getKey().matches("^\\d.*") ? "id_" + entry.getKey() : entry.getKey(); xmlGen.writeFieldName(safeKey); serializers.defaultSerializeValue(entry.getValue(), gen); } } }
3. 排查请求头差异
确认Docker环境中发起的请求是否携带了Accept: application/xml头,导致Spring Boot优先选择XML转换器。可以用curl指定Accept头测试:
curl -H "Accept: application/json" http://your-service-address/your-api-path
如果测试正常,说明是请求头的问题,可在网关或客户端统一配置Accept: application/json。
4. 禁用XML转换器(不需要XML支持的场景)
如果系统不需要XML响应,可以直接排除Jackson XML的自动配置:
@SpringBootApplication(exclude = {JacksonAutoConfiguration.class}) public class YourApplication { @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } }
或者移除jackson-dataformat-xml依赖,避免XML转换器被自动加载。
内容的提问来源于stack exchange,提问作者Den B
相关产品推荐
相关产品推荐

