在 Java 生态中,主要有以下几种方式来实现 XML 序列化/反序列化:

- JAXB (Java Architecture for XML Binding):这是目前最推荐、最标准的方式,从 Java 6 开始被内置到 JDK 中,它使用注解来简化整个过程。
- DOM / SAX / StAX 解析器:这些是底层的 XML API,DOM 将整个 XML 文档加载到内存中形成树状结构;SAX 是事件驱动的流式解析;StAX 是更现代的流式 API,它们非常灵活,但代码量较大,通常不直接用于简单的对象-XML 映射。
- 第三方库:如 XStream,它非常简单易用,但需要额外引入依赖。
下面,我们将重点讲解最主流的 JAXB 方式,并简要提及其他方法。
使用 JAXB (推荐)
JAXB 通过将 Java 字段/属性与 XML 元素/属性绑定,实现了对象和 XML 之间的自动转换,核心是 javax.xml.bind 包。
核心注解
@XmlRootElement: 将一个类映射为 XML 的根元素。@XmlElement: 将一个字段/属性映射为 XML 的一个元素。@XmlAttribute: 将一个字段/属性映射为 XML 元素的一个属性。@XmlAccessorType: 控制哪些字段/属性会被映射,通常使用XmlAccessType.FIELD或XmlAccessType.PROPERTY。@XmlElementWrapper: 用于包装一个集合类型的元素,<books><book>...</book></books>。
示例:完整的序列化与反序列化流程
假设我们有一个 User 类,需要将其转换为 XML。
准备 Java 类
创建一个 Java 类,并使用 JAXB 注解进行标记。

import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
// 1. 定义这个类是 XML 的根元素,name 指定 XML 标签名
@XmlRootElement(name = "user")
// 2. 指定哪些字段需要被序列化,FIELD 表示所有非 static、非 transient 的字段
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
// 3. 将此字段映射为 XML 元素的属性
@XmlAttribute
private int id;
// 4. 将此字段映射为 XML 元素
@XmlElement
private String name;
@XmlElement
private String email;
// 5. 使用 @XmlElementWrapper 包装列表,并指定列表项的标签名
@XmlElementWrapper(name = "phoneNumbers")
@XmlElement(name = "phone")
private List<String> phoneNumbers;
// JAXB 需要一个无参构造函数
public User() {
}
// 带参构造函数,方便创建对象
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
this.phoneNumbers = new ArrayList<>();
}
// Getters and Setters (JAXB 在序列化/反序列化时会使用它们)
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> getPhoneNumbers() { return phoneNumbers; }
public void setPhoneNumbers(List<String> phoneNumbers) { this.phoneNumbers = phoneNumbers; }
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", phoneNumbers=" + phoneNumbers +
'}';
}
}
序列化:将 Java 对象转换为 XML
创建一个工具类来执行序列化。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;
public class JaxbSerializer {
public static String toXml(Object object) throws JAXBException {
// 1. 创建 JAXBContext 实例,参数是需要序列化的类的 Class 对象
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
// 2. 创建 Marshaller 实例,用于执行序列化操作
Marshaller marshaller = jaxbContext.createMarshaller();
// 3. 设置输出格式,例如美化输出(换行和缩进)
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 4. 使用 StringWriter 来捕获输出的 XML 字符串
StringWriter writer = new StringWriter();
// 5. 执行序列化,将对象写入到 writer 中
marshaller.marshal(object, writer);
// 6. 返回 XML 字符串
return writer.toString();
}
public static void main(String[] args) {
User user = new User(1, "张三", "zhangsan@example.com");
user.getPhoneNumbers().add("13800138000");
user.getPhoneNumbers().add("13900139000");
try {
String xml = toXml(user);
System.out.println("序列化后的 XML:");
System.out.println(xml);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
运行结果 (序列化后的 XML):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user id="1">
<name>张三</name>
<email>zhangsan@example.com</email>
<phoneNumbers>
<phone>13800138000</phone>
<phone>13900139000</phone>
</phoneNumbers>
</user>
反序列化:将 XML 转换为 Java 对象
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
public class JaxbDeserializer {
public static <T> T fromXml(String xml, Class<T> clazz) throws JAXBException {
// 1. 创建 JAXBContext 实例
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
// 2. 创建 Unmarshaller 实例,用于执行反序列化操作
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// 3. 使用 StringReader 来读取 XML 字符串
StringReader reader = new StringReader(xml);
// 4. 执行反序列化,将 XML 转换为 Java 对象
// unmarshal() 的返回值是 XML 根元素对应的 Java 对象
return (T) unmarshaller.unmarshal(reader);
}
public static void main(String[] args) {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<user id=\"1\">\n" +
" <name>张三</name>\n" +
" <email>zhangsan@example.com</email>\n" +
" <phoneNumbers>\n" +
" <phone>13800138000</phone>\n" +
" <phone>13900139000</phone>\n" +
" </phoneNumbers>\n" +
"</user>";
try {
User user = fromXml(xml, User.class);
System.out.println("反序列化后的 User 对象:");
System.out.println(user);
System.out.println("Name: " + user.getName());
System.out.println("Email: " + user.getEmail());
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
运行结果 (反序列化后的 User 对象):
反序列化后的 User 对象:
User{id=1, name='张三', email='zhangsan@example.com', phoneNumbers=[13800138000, 13900139000]}
Name: 张三
Email: zhangsan@example.com
使用第三方库 XStream
XStream 以其简洁的 API 而闻名,无需注解,直接使用反射即可完成映射。

添加依赖
如果你使用 Maven,在 pom.xml 中添加:
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.20</version> <!-- 使用最新版本 -->
</dependency>
序列化示例
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
public class XStreamSerializer {
public static String toXml(Object object) {
XStream xstream = new XStream(new DomDriver());
// 可以设置别名,使 XML 更简洁
xstream.alias("user", User.class);
xstream.aliasField("id", User.class, "id"); // 将 User 的 id 字段映射为 XML 的 id 元素
xstream.aliasField("name", User.class, "name");
xstream.aliasField("email", User.class, "email");
xstream.aliasField("phoneNumbers", User.class, "phoneNumbers");
xstream.addImplicitCollection(User.class, "phoneNumbers", "phone", String.class); // 隐式集合
return xstream.toXML(object);
}
public static void main(String[] args) {
User user = new User(1, "李四", "lisi@example.com");
user.getPhoneNumbers().add("13700137000");
String xml = toXml(user);
System.out.println("XStream 序列化后的 XML:");
System.out.println(xml);
}
}
反序列化示例
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
public class XStreamDeserializer {
public static <T> T fromXml(String xml, Class<T> clazz) {
XStream xstream = new XStream(new DomDriver());
xstream.alias("user", User.class);
// ... (和序列化时相同的别名设置)
return (T) xstream.fromXML(xml);
}
public static void main(String[] args) {
String xml = "<user>\n" +
" <id>1</id>\n" +
" <name>李四</name>\n" +
" <email>lisi@example.com</email>\n" +
" <phoneNumbers>\n" +
" <phone>13700137000</phone>\n" +
" </phoneNumbers>\n" +
"</user>";
User user = fromXml(xml, User.class);
System.out.println("XStream 反序列化后的 User 对象:");
System.out.println(user);
}
}
使用标准 API (DOM/SAX)
这种方法非常底层,代码冗长,通常只在需要复杂的、非标准的 XML 操作时使用,不推荐用于简单的对象-XML 映射。
简单的 DOM 序列化示例 (不推荐用于对象映射)
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
public class DomSerializer {
public static String toXml(User user) throws Exception {
// 1. 创建 DocumentBuilderFactory 和 DocumentBuilder
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// 2. 创建新的 Document 对象
Document doc = docBuilder.newDocument();
// 3. 创建根元素
Element rootElement = doc.createElement("user");
rootElement.setAttribute("id", String.valueOf(user.getId()));
doc.appendChild(rootElement);
// 4. 创建子元素
Element nameElement = doc.createElement("name");
nameElement.appendChild(doc.createTextNode(user.getName()));
rootElement.appendChild(nameElement);
Element emailElement = doc.createElement("email");
emailElement.appendChild(doc.createTextNode(user.getEmail()));
rootElement.appendChild(emailElement);
// 5. 将 Document 对象转换为 XML 字符串
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(writer));
return writer.toString();
}
public static void main(String[] args) throws Exception {
User user = new User(2, "王五", "wangwu@example.com");
String xml = toXml(user);
System.out.println("DOM 序列化后的 XML:");
System.out.println(xml);
}
}
总结与对比
| 特性 | JAXB (推荐) | XStream (第三方) | DOM/SAX (标准 API) |
|---|---|---|---|
| 易用性 | 高,注解驱动,代码简洁 | 非常高,几乎零配置,代码最简洁 | 低,需要手动构建和解析 XML 树 |
| 性能 | 良好 | 良好 | 对于大文件,SAX/StAX 性能更好 |
| 灵活性 | 良好,通过注解控制映射 | 极高,支持别名、转换器、过滤器等 | 极高,可以完全控制 XML 的生成和解析 |
| 依赖 | JDK 内置 (Java 6+) | 需要额外引入 xstream 库 |
JDK 内置 |
| 适用场景 | 标准、对象到 XML 的映射,Web 服务等 | 快速原型开发,需要高度自定义 XML 格式 | 复杂的 XML 处理,如修改现有 XML、处理超大文件等 |
对于绝大多数 Java 应用程序,JAXB 是处理 XML 序列化和反序列化的最佳选择,它是标准、高效且易于使用的,只有在需要 JAXB 无法满足的特殊灵活性,或者希望最小化项目依赖时,才考虑 XStream,而 DOM/SAX 则应留给那些需要精细操作 XML 结构的底层任务。
