如何配置Jackson2 XmlMapper自动识别重复XML子节点并转为命名数组
问题描述
我用这段代码把XML转成JSON:
ObjectMapper xmlMapper = new XmlMapper(); JsonNode jsonNode = xmlMapper.readTree("<fakeRoot>" + xmlText + "</fakeRoot>"); String jsonString = jsonNode.toString(); System.out.println("jsonString = " + jsonString);
其中xmlText的内容是:
<a> <b> <c>xxxx</c> </b> <b> <c>yyyy</c> </b> <b> <c>zzzz</c> </b> </a>
我想要生成的JSON是这样的:
{ "a": { "b": [ { "c": "xxxx" }, { "c": "yyyy" }, { "c": "zzzz" } ] } }
但XmlMapper实际返回的却是错误的结果:
{"a":{"b":{"c":"zzzz"}}}
请问这是为什么?怎么配置XmlMapper生成预期的JSON(不用给"a"、"b"、"c"写Java类)?如何让XmlMapper自动识别重复的XML子节点并转成数组?
原因分析
XML本身没有数组的概念,重复的同名节点只是同一元素的多次出现。Jackson的XmlMapper默认处理逻辑是:遇到重复的同名节点时,后面的节点会覆盖前面的,最终只保留最后一个节点的内容,这就是结果里只有zzzz的原因。
解决方案
要让XmlMapper自动把重复节点转为数组,不需要定义Java类,只需要调整XmlMapper的配置即可:
- 创建
JacksonXmlModule并关闭默认的包装器行为,让重复节点不会被当作包装器内的元素处理; - 可选:启用
ACCEPT_SINGLE_VALUE_AS_ARRAY特性,确保单个节点也能被识别为数组(如果需要单节点场景也生成数组的话); - 用配置好的模块初始化
XmlMapper。
修改后的代码如下:
JacksonXmlModule module = new JacksonXmlModule(); // 关闭默认包装器,让重复节点直接转为数组 module.setDefaultUseWrapper(false); XmlMapper xmlMapper = new XmlMapper(module); // 启用该特性,确保单个节点也能被转为数组(可选) xmlMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); // 后续解析代码不变 JsonNode jsonNode = xmlMapper.readTree("<fakeRoot>" + xmlText + "</fakeRoot>"); String jsonString = jsonNode.toString(); System.out.println("jsonString = " + jsonString);
这样配置后,XmlMapper会自动识别重复的<b>节点,将其转为JSON数组,生成你预期的结果。如果不需要单个节点转数组,可以去掉enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)这一行。
内容的提问来源于stack exchange,提问作者Sorin Postelnicu
相关产品推荐
相关产品推荐

