杰瑞科技汇

java xml 转object

  1. JAXB (Java Architecture for XML Binding) - Java 标准内置,非常流行且易于使用。
  2. Jackson with XML Extension - 性能极佳,是许多现代 Web 服务的首选。
  3. DOM/SAX 解析 - 底层 API,最灵活但代码也最繁琐,适用于复杂或非标准的 XML 处理。

准备工作:定义 XML 和 Java 对象

为了演示,我们首先定义一个简单的 XML 结构和与之对应的 Java 类。

java xml 转object-图1
(图片来源网络,侵删)

示例 XML (user.xml):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
    <id>101</id>
    <name>张三</name>
    <email>zhangsan@example.com</email>
    <roles>
        <role>ADMIN</role>
        <role>USER</role>
    </roles>
</user>

使用 JAXB (推荐)

JAXB 从 Java 6 开始就是标准库的一部分,无需额外依赖,它通过注解将 XML 元素与 Java 对象的字段绑定。

创建 Java 类

import javax.xml.bind.annotation.*;
import java.util.List;
// 根节点 <user> 对应 User 类
@XmlRootElement(name = "user")
// 控制序列化/反序列化时是否输出字段名(如 <id> 而不是 <User_id>)
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
    // <id> 标签对应 id 字段
    @XmlElement(name = "id")
    private int id;
    // <name> 标签对应 name 字段
    @XmlElement(name = "name")
    private String name;
    // <email> 标签对应 email 字段
    @XmlElement(name = "email")
    private String email;
    // <roles> 标签对应 roles 字段
    @XmlElement(name = "role") // 指定列表中每个元素的标签名
    private List<String> roles;
    // 必须提供一个无参构造函数,JAXB 内部会使用它
    public User() {
    }
    // Getters and Setters (标准 JavaBean 规范)
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public List<String> getRoles() { return roles; }
    public void setRoles(List<String> roles) { this.roles = roles; }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", roles=" + roles +
                '}';
    }
}

编写转换代码

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Marshaller;
import java.io.File;
public class JaxbExample {
    public static void main(String[] args) {
        // --- XML 文件路径 ---
        File xmlFile = new File("user.xml");
        try {
            // 1. 创建 JAXBContext,传入需要绑定的类
            JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
            // 2. 创建 Unmarshaller(用于将 XML 转为对象)
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            // 3. 执行 unmarshal 操作,将 XML 文件转换为 User 对象
            // unmarshal() 方法返回的是 Object,需要强制类型转换
            User user = (User) jaxbUnmarshaller.unmarshal(xmlFile);
            // 4. 打印结果
            System.out.println("JAXB 解析成功!");
            System.out.println(user);
            // --- (可选) 对象转回 XML ---
            System.out.println("\n--- 将对象转回 XML ---");
            Marshaller marshaller = jaxbContext.createMarshaller();
            // 格式化输出,使 XML 更易读
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            // 输出到控制台
            marshaller.marshal(user, System.out);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果

JAXB 解析成功!
User{id=101, name='张三', email='zhangsan@example.com', roles=[ADMIN, USER]}
--- 将对象转回 XML ---
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
    <id>101</id>
    <name>张三</name>
    <email>zhangsan@example.com</email>
    <role>ADMIN</role>
    <role>USER</role>
</user>

使用 Jackson with XML Extension

Jackson 是一个非常流行的 JSON 库,但它也支持 XML,它通常被认为比 JAXB 性能更好,并且是 Spring Boot 等框架的默认选择。

添加 Maven 依赖

你需要在你的 pom.xml 文件中添加 Jackson 的 XML 模块依赖。

java xml 转object-图2
(图片来源网络,侵删)
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- 使用最新版本 -->
</dependency>

创建 Java 类

Jackson 的注解与 JAXB 类似,但有一些细微差别。@JacksonXmlProperty 是其核心注解之一。

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;
// 指定根元素的名称和命名空间
@JacksonXmlRootElement(localName = "user")
public class UserJackson {
    // localName 指定 XML 中的标签名
    @JacksonXmlProperty(localName = "id")
    private int id;
    @JacksonXmlProperty(localName = "name")
    private String name;
    @JacksonXmlProperty(localName = "email")
    private String email;
    // @JacksonXmlElementWrapper 用于包装集合元素,可以指定包装标签的名称
    @JacksonXmlElementWrapper(localName = "roles")
    // @JacksonXmlProperty 指定集合中每个元素的标签名
    @JacksonXmlProperty(localName = "role")
    private List<String> roles;
    public UserJackson() {
    }
    // Getters and Setters
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public List<String> getRoles() { return roles; }
    public void setRoles(List<String> roles) { this.roles = roles; }
    @Override
    public String toString() {
        return "UserJackson{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", roles=" + roles +
                '}';
    }
}

编写转换代码

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
public class JacksonExample {
    public static void main(String[] args) {
        File xmlFile = new File("user.xml");
        try {
            // 1. 创建 XmlMapper,这是 Jackson 处理 XML 的核心类
            XmlMapper xmlMapper = new XmlMapper();
            // 2. 使用 readValue 方法直接将文件内容读取到对象中
            UserJackson user = xmlMapper.readValue(xmlFile, UserJackson.class);
            // 3. 打印结果
            System.out.println("Jackson 解析成功!");
            System.out.println(user);
            // --- (可选) 对象转回 XML ---
            System.out.println("\n--- 将对象转回 XML ---");
            String xmlOutput = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
            System.out.println(xmlOutput);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果

与方法一类似,输出一个 UserJackson 对象和格式化的 XML 字符串。


使用 DOM (文档对象模型) 解析

这是最底层的 API,它将整个 XML 文档读入内存,构建一个树形结构(DOM Tree),然后你可以在树中导航来查找和修改数据。

编写转换代码

import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.File;
public class DomExample {
    public static void main(String[] args) {
        File xmlFile = new File("user.xml");
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            // 1. 创建 DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 2. 解析 XML 文件,创建 Document 对象(DOM 树的根)
            Document document = builder.parse(xmlFile);
            // 3. 获取根元素 <user>
            Element userElement = document.getDocumentElement();
            // 4. 创建一个简单的 Java 对象来存储数据
            User user = new User(); // 假设我们复用方法一中的 User 类
            // 5. 通过标签名获取子元素,并获取其文本内容
            NodeList idList = userElement.getElementsByTagName("id");
            if (idList.getLength() > 0) {
                user.setId(Integer.parseInt(idList.item(0).getTextContent()));
            }
            NodeList nameList = userElement.getElementsByTagName("name");
            if (nameList.getLength() > 0) {
                user.setName(nameList.item(0).getTextContent());
            }
            NodeList emailList = userElement.getElementsByTagName("email");
            if (emailList.getLength() > 0) {
                user.setEmail(emailList.item(0).getTextContent());
            }
            // 6. 处理列表 <roles>
            NodeList roleList = userElement.getElementsByTagName("role");
            for (int i = 0; i < roleList.getLength(); i++) {
                Node roleNode = roleList.item(i);
                if (roleNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element roleElement = (Element) roleNode;
                    // 这里需要手动维护一个列表,非常繁琐
                    // 简化示例,只取第一个 role
                    user.getRoles().add(roleElement.getTextContent());
                    break; 
                }
            }
            // 实际项目中,处理列表需要更复杂的代码来循环和添加
            // 7. 打印结果
            System.out.println("DOM 解析成功!");
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

总结与对比

特性 JAXB Jackson (XML) DOM/SAX
易用性 非常高,注解清晰,代码简洁 ,API 简洁,类似 Jackson JSON ,需要大量手动操作,代码冗长
性能 良好 非常高,通常优于 JAXB DOM: 加载整个文档到内存,大文件时性能差、耗内存
SAX: 流式解析,内存占用小,速度快
依赖 Java 标准库 (JDK 6+),无需额外依赖 需要添加 jackson-dataformat-xml 依赖 Java 标准库 (JDK 1+),无需额外依赖
灵活性 适用于标准的、结构化的 XML 适用于标准的、结构化的 XML,且支持复杂配置 极高,可以处理任何格式的 XML,包括非结构化的
主要用途 Web 服务 (SOAP, JAX-WS),配置文件 RESTful Web 服务 (支持 JSON/XML),高性能应用 复杂的 XML 解析任务,需要精细控制或处理“畸形”XML
学习曲线

如何选择?

  • 如果你在开发一个标准的 Java 应用(非 Web 服务),并且希望使用最简单、最直接的方式JAXB 是最佳选择,它无需任何外部依赖,且非常稳定。
  • 如果你在开发一个现代的 RESTful API,或者对性能有极高要求,或者项目已经在使用 Jackson 处理 JSONJackson with XML 是不二之选,它在性能和易用性之间取得了很好的平衡。
  • 如果你需要处理一个非常巨大(GB 级别)的 XML 文件,或者 XML 结构非常不规则、复杂,甚至格式有些问题:你应该考虑 SAX 解析器,因为它不会将整个文件加载到内存中,如果需要随机访问或修改 XML 的任何部分,DOM 是唯一的选择,但要准备好处理其内存消耗和复杂性。

对于绝大多数日常开发任务,JAXBJackson 是更优、更现代的选择。

java xml 转object-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇