如何使用 Jackson 反序列化任意深度嵌套的 XML 结构

来源:Vuejs社区作者:香港程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《如何使用 Jackson 反序列化任意深度嵌套的 XML 结构》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何使用 Jackson 反序列化任意深度嵌套的 XML 结构》有用,将其分享出去将是对创作者最好的鼓励。

Jackson是Java生态中广泛使用的序列化反序列化工具,除了处理JSON数据外,通过扩展模块也支持XML格式的处理,针对任意深度嵌套的XML结构,不需要预先定义固定层级的实体类,可通过灵活的API完成反序列化操作。

如何使用 Jackson 反序列化任意深度嵌套的 XML 结构

依赖准备

要使用Jackson处理XML,需要引入核心依赖和XML扩展依赖,Maven项目可在pom.xml中添加如下配置:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version>
</dependency>

使用JsonNode处理任意嵌套XML

Jackson的XmlMapper可以将XML直接反序列化为JsonNode树结构,这种方式不需要预先定义实体类,适合处理任意深度和未知结构的XML,JsonNode提供了遍历子节点、获取节点值的方法,可递归处理嵌套内容。

基础示例

假设有如下任意深度的嵌套XML:

<root>
    <level1>
        <level2>
            <level3>
                <value>测试内容</value>
            </level3>
        </level2>
    </level1>
    <other>额外节点</other>
</root>

反序列化并遍历的代码如下:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.IOException;

public class XmlDeserializeDemo {
    public static void main(String[] args) throws IOException {
        String xmlContent = "<root>" +
                "<level1>" +
                "<level2>" +
                "<level3>" +
                "<value>测试内容</value>" +
                "</level3>" +
                "</level2>" +
                "</level1>" +
                "<other>额外节点</other>" +
                "</root>";
        XmlMapper xmlMapper = new XmlMapper();
        JsonNode rootNode = xmlMapper.readTree(xmlContent);
        // 递归遍历所有节点
        traverseNode(rootNode, 0);
    }

    private static void traverseNode(JsonNode node, int depth) {
        // 输出当前节点名称和值
        if (node.isValueNode()) {
            for (int i = 0; i < depth; i++) {
                System.out.print("  ");
            }
            System.out.println("节点值: " + node.asText());
        } else if (node.isContainerNode()) {
            for (int i = 0; i < depth; i++) {
                System.out.print("  ");
            }
            System.out.println("节点名: " + node.fieldNames().next());
            // 遍历子节点
            node.forEach(child -> traverseNode(child, depth + 1));
        }
    }
}

处理同名嵌套节点

如果XML中存在同名的多层嵌套节点,比如如下结构:

<items>
    <item>
        <item>
            <item>深层内容</item>
        </item>
    </item>
</items>

可以通过JsonNodepath方法逐层获取,或者通过循环遍历所有子节点:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.IOException;

public class NestedSameNameDemo {
    public static void main(String[] args) throws IOException {
        String xml = "<items>" +
                "<item>" +
                "<item>" +
                "<item>深层内容</item>" +
                "</item>" +
                "</item>" +
                "</items>";
        XmlMapper xmlMapper = new XmlMapper();
        JsonNode root = xmlMapper.readTree(xml);
        JsonNode current = root.path("item");
        int level = 1;
        while (current.isContainerNode() && current.has("item")) {
            System.out.println("第" + level + "层item节点");
            current = current.path("item");
            level++;
        }
        if (current.isValueNode()) {
            System.out.println("最深层item内容: " + current.asText());
        }
    }
}

自定义反序列化器适配复杂嵌套

如果需要将嵌套XML转换为自定义的Java对象结构,可自定义反序列化器,在反序列化过程中动态处理任意深度的嵌套逻辑。首先需要定义一个通用的嵌套结构实体类:

import java.util.ArrayList;
import java.util.List;

public class NestedXmlNode {
    private String name;
    private String value;
    private List<NestedXmlNode> children = new ArrayList<>();

    // getter和setter方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public List<NestedXmlNode> getChildren() {
        return children;
    }

    public void setChildren(List<NestedXmlNode> children) {
        this.children = children;
    }
}

然后自定义反序列化器:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

public class NestedXmlDeserializer extends StdDeserializer<NestedXmlNode> {
    protected NestedXmlDeserializer() {
        super(NestedXmlNode.class);
    }

    @Override
    public NestedXmlNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        return parseNode(node);
    }

    private NestedXmlNode parseNode(JsonNode node) {
        NestedXmlNode xmlNode = new NestedXmlNode();
        if (node.isValueNode()) {
            xmlNode.setValue(node.asText());
            return xmlNode;
        }
        // 处理容器节点
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        if (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            xmlNode.setName(entry.getKey());
            JsonNode childNode = entry.getValue();
            if (childNode.isContainerNode()) {
                // 递归解析子节点
                childNode.fields().forEachRemaining(childEntry -> {
                    NestedXmlNode child = parseNode(childEntry.getValue());
                    child.setName(childEntry.getKey());
                    xmlNode.getChildren().add(child);
                });
            } else {
                xmlNode.setValue(childNode.asText());
            }
        }
        return xmlNode;
    }
}

最后注册反序列化器并使用:

import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.IOException;

public class CustomDeserializerDemo {
    public static void main(String[] args) throws IOException {
        String xml = "<root>" +
                "<a>" +
                "<b>" +
                "<c>内容</c>" +
                "</b>" +
                "</a>" +
                "</root>";
        XmlMapper xmlMapper = new XmlMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(NestedXmlNode.class, new NestedXmlDeserializer());
        xmlMapper.registerModule(module);
        NestedXmlNode result = xmlMapper.readValue(xml, NestedXmlNode.class);
        System.out.println("根节点名: " + result.getName());
        System.out.println("子节点数量: " + result.getChildren().size());
    }
}

注意事项

  • XmlMapper默认会将XML的属性和文本内容做特定映射,如果XML包含属性,需要在配置中开启对应支持,避免属性被忽略。
  • 处理超大深度的嵌套XML时,递归遍历可能出现栈溢出,可将递归改为栈或队列的迭代方式实现。
  • 如果XML结构中存在命名空间,需要在XmlMapper中配置对应的命名空间处理策略,否则可能出现节点解析错误。

JacksonXML反序列化嵌套结构XmlMapper修改时间:2026-06-24 17:33:47

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。