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

如何使用Jackson/FasterXML读取XML时仅保留指定节点及子节点?

如何用Jackson FasterXML只读取XML中的指定节点?

针对你遇到的这个要从海量XML节点中只提取特定字段的需求,Jackson其实提供了很直接的解决方案——通过忽略未知字段+精准映射目标节点来实现,哪怕目标节点嵌套层级很深也没问题。下面一步步来解决你的问题:

1. 第一步:配置Jackson忽略未知字段

生产环境中employee标签下有大量你不需要的节点,首先得告诉Jackson不要因为这些未定义的字段抛出反序列化异常。有两种方式可以实现:

方式一:全局配置XmlMapper

XmlMapper objectMapper = new XmlMapper();
// 关闭"未知属性失败"的特性,忽略所有未在POJO中定义的字段
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

方式二:在POJO类上添加注解(更推荐,粒度更细)

直接在Employee类上加上@JsonIgnoreProperties(ignoreUnknown = true),这样只会忽略这个类下的未知字段,不会影响其他POJO的反序列化行为。

2. 第二步:设计对应的POJO结构

现在只需要映射first_name、last_name和嵌套的node100及其子节点。这里针对嵌套场景给出标准实现:

首先定义Node100的结构(对应它的子节点)

public class Node100 {
    // 因为<values>下是多个<value>节点,用List来接收,关闭自动包装
    @JacksonXmlElementWrapper(localName = "values", useWrapping = false)
    private List<String> value;

    // getter和setter
    public List<String> getValue() {
        return value;
    }

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

然后定义中间的父节点类(按实际嵌套层级调整)

假设node100嵌套在parent1 -> parent2层级下,对应定义两个父类:

// 对应嵌套的第二层父节点
public class Parent2 {
    @JacksonXmlProperty(localName = "node100")
    private Node100 node100;

    // getter和setter
    public Node100 getNode100() {
        return node100;
    }

    public void setNode100(Node100 node100) {
        this.node100 = node100;
    }
}

// 对应嵌套的第一层父节点
public class Parent1 {
    @JacksonXmlProperty(localName = "parent2")
    private Parent2 parent2;

    // getter和setter
    public Parent2 getParent2() {
        return parent2;
    }

    public void setParent2(Parent2 parent2) {
        this.parent2 = parent2;
    }
}

最后调整Employee和Employees类

@JsonIgnoreProperties(ignoreUnknown = true) // 关键:忽略所有未定义的字段
public final class Employee {
    @JacksonXmlProperty(localName = "first_name")
    private String firstName;

    @JacksonXmlProperty(localName = "last_name")
    private String lastName;

    @JacksonXmlProperty(localName = "parent1") // 对应嵌套的第一层父节点
    private Parent1 parent1;

    // getter和setter
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Parent1 getParent1() {
        return parent1;
    }

    public void setParent1(Parent1 parent1) {
        this.parent1 = parent1;
    }

    // 可以加个快捷方法,直接获取node100,不用逐层调用
    public Node100 getNode100() {
        if (parent1 != null && parent1.getParent2() != null) {
            return parent1.getParent2().getNode100();
        }
        return null;
    }
}

@JacksonXmlRootElement(localName = "employees")
public final class Employees {
    // 用List代替数组,更灵活,避免空指针问题
    @JacksonXmlElementWrapper(localName = "employee", useWrapping = false)
    private List<Employee> employees;

    // getter和setter
    public List<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
}

3. 第三步:调整反序列化代码

把之前的代码加上忽略未知字段的配置,然后测试:

public static void main(String[] args) throws IOException {
    XmlMapper objectMapper = new XmlMapper();
    // 全局配置忽略未知属性(如果已经在POJO上加了注解,这一步可以省略)
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    // 读取XML文件
    Path xmlPath = Paths.get("C:\\Users\\91895\\Downloads\\File\\XmlFile.xml");
    String xmlContent = Files.readString(xmlPath, StandardCharsets.UTF_8);

    // 反序列化为POJO
    Employees employees = objectMapper.readValue(xmlContent, Employees.class);

    // 测试输出提取到的字段
    for (Employee emp : employees.getEmployees()) {
        System.out.println("First Name: " + emp.getFirstName());
        System.out.println("Last Name: " + emp.getLastName());
        Node100 node100 = emp.getNode100();
        if (node100 != null && node100.getValue() != null) {
            System.out.println("Node100 Values: " + String.join(", ", node100.getValue()));
        }
        System.out.println("---");
    }
}

几个关键注意点

  • 确保@JacksonXmlProperty的localName和XML中的节点名称完全一致(XML节点名称是大小写敏感的)
  • 如果node100可能不存在,对应的字段要允许为null(不要用基本类型,用包装类或List这类引用类型)
  • 用List代替数组,不仅更灵活,还能避免空指针问题

内容的提问来源于stack exchange,提问作者Pale Blue Dot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:12:58