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

使用FasterXML解析多层嵌套XML时能否避免创建额外类?

解析多层嵌套XML又不想写一堆POJO?试试这几个方法

问题背景

要解析的XML是多层嵌套结构,每一层只有一个子元素,示例结构如下:

<xml>
  <level1>
    <level2>
      <level3>
        <actualData>123</actualData>

本来想用@JacksonXmlElementWrapper跳过包装类,但这个注解的localName只能传单个值,没法像下面这种无效写法那样指定多层路径:

@JacksonXmlElementWrapper(localName = ["level1", "level2", "level3"]) // 无效写法,localName只接受单个参数
@JacksonXmlProperty(localName = "actualData")
private String actualData;

需求很明确:解析这个嵌套XML,但不想为level1、level2、level3单独写POJO类。


可行方案

1. 直接用路径表达式(Jackson 2.12+)

Jackson从2.12版本开始支持在@JacksonXmlProperty里用点分隔的完整路径,一步到位指定嵌套层级,完全不用额外POJO:

@JacksonXmlRootElement(localName = "xml")
public class XmlData {
    @JacksonXmlProperty(localName = "level1.level2.level3.actualData")
    private String actualData;

    // 别忘了加getter和setter
    public String getActualData() { return actualData; }
    public void setActualData(String actualData) { this.actualData = actualData; }
}

解析的时候正常用XmlMapper就行:

XmlMapper mapper = new XmlMapper();
XmlData data = mapper.readValue(xmlContent, XmlData.class);

这个方法最简单,只要版本够就优先用。

2. 自定义反序列化器(兼容低版本Jackson)

如果你的Jackson版本低于2.12,那就自己写个反序列化器,手动遍历XML节点:

@JacksonXmlRootElement(localName = "xml")
public class XmlData {
    @JsonDeserialize(using = NestedDataDeserializer.class)
    private String actualData;

    // getter和setter
}

class NestedDataDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        XmlParser xmlParser = (XmlParser) p;
        // 一层一层找节点
        xmlParser.nextTag();
        if (!"level1".equals(xmlParser.getCurrentName())) {
            throw new IOException("找不到<level1>标签");
        }
        xmlParser.nextTag();
        if (!"level2".equals(xmlParser.getCurrentName())) {
            throw new IOException("找不到<level2>标签");
        }
        xmlParser.nextTag();
        if (!"level3".equals(xmlParser.getCurrentName())) {
            throw new IOException("找不到<level3>标签");
        }
        xmlParser.nextTag();
        if (!"actualData".equals(xmlParser.getCurrentName())) {
            throw new IOException("找不到<actualData>标签");
        }
        return xmlParser.getText();
    }
}

虽然代码啰嗦点,但能兼容老版本,完全可控。

3. 用树模型直接取数

不想改POJO的话,还可以用Jackson的树模型先把整个XML解析成JsonNode,再通过路径直接拿值:

XmlMapper mapper = new XmlMapper();
JsonNode root = mapper.readTree(xmlContent);
String actualData = root.path("level1").path("level2").path("level3").path("actualData").asText();

这种方式最灵活,不用定义任何注解,适合临时解析或者XML结构偶尔变动的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:08:13