Spring中Jackson解析0开头XML标签报错解决方案
问题根因
这个报错来自两个核心问题,和Spring、Jackson版本无直接关系:
- 配置错误:当前
RestTemplate没有配置专用的XML消息转换器,默认调用了Jackson JSON解析器处理XML响应,日志里的JSON parse error就是直接证据——解析XML响应时本不该触发JSON解析逻辑。 - 源内容非法:你拿到的XML本身不符合W3C XML 1.0命名规范:XML元素标签名禁止以数字、特殊字符开头,必须以字母、下划线开头,响应里的
<064E>、<00A5>、<8132>这类以数字开头的标签本身就是非法XML节点,所有合规XML解析器直接解析都会报错,这也是你删掉这类标签后流程能跑通的核心原因。
解决方案
按以下步骤调整即可,不需要修改上游返回的业务数据:
1. 引入XML解析依赖
首先给项目添加Jackson XML解析依赖,版本和项目现有Jackson版本保持一致即可,Maven依赖如下:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
2. 预处理非法XML标签
因为上游返回的数字开头标签不符合规范,无法直接修改上游输出的情况下,在解析前做一层轻量替换,把所有数字开头的标签名前面加下划线前缀,转成合法XML格式即可,下划线前缀不会影响你后续取标签对应的键值。
3. 调整解析逻辑
不要直接让RestTemplate自动把响应转成ResponseDto,先获取原始字符串做预处理,再用专门的XmlMapper完成对象映射,参考代码如下:
// 1. 先获取原始XML响应字符串 String rawXml = restTemplate.getForObject(url, String.class, urlParameter); // 2. 正则替换所有数字开头的起始/闭合标签,补下划线前缀转成合法XML // 例:<064E> 转 <_064E>,</064E> 转 </_064E> String validXml = rawXml.replaceAll("<(/?)([0-9][^>/]*)>", "<$1_$2>"); // 3. 配置XML解析器 XmlMapper xmlMapper = new XmlMapper(); // 忽略DTO里没定义的未知节点 xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 支持同名重复标签(比如多个<PR_NUMBERS>)自动转成集合 xmlMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); // 4. 完成映射 ResponseDto responseDto = xmlMapper.readValue(validXml, ResponseDto.class);
4. 调整DTO适配XML解析
把原来DTO上的JSON系列注解替换成Jackson XML对应的注解,处理嵌套节点的映射问题:
- 原
@JsonIgnoreProperties(ignoreUnknown = true)可以直接通过上面XmlMapper的全局配置实现,不需要单独加注解 - 注意
steps节点是两层嵌套:外层是根节点下的<steps>,里面又包了一层<steps>列表,可以在Step类上加对应注解,或者调整DTO字段结构匹配层级 variables下的多个<PR_NUMBERS>重复标签,用List<String>接这个字段会比直接用Object更稳定,避免类型转换异常- 解析后如果要取原始的数字开头节点名(比如
064E),把Map key前面的下划线前缀去掉即可。
可选优化
如果接口响应体很大,正则替换字符串的性能不够,可以自定义XMLStreamReader装饰器,在读取XML事件流的时候动态给数字开头的标签名补前缀,不需要全量替换字符串,性能会更高,逻辑和上面的正则替换完全一致,只是把处理时机从字符串阶段移到了流读取阶段。
注意:不要用JAXB作为XML解析器,JAXB对非法XML的容错性极差,遇到这类不符合规范的标签会直接抛出致命错误,没有灵活的扩展点做兼容处理。
内容的提问来源于stack exchange,提问作者ale.soft
相关产品推荐
相关产品推荐

