使用 Jackson 进行 XML 序列化和反序列化
上次更新:2024 年 1 月 8 日
1. 概述
在本教程中,我们将学习如何使用 Jackson 2.x 将 Java 对象序列化为 XML 数据,并将其反序列化回 POJO。
我们将专注于基本的操作,这些操作不需要太多的复杂性或自定义。
2. XmlMapper 对象
XmlMapper 是 Jackson 2.x 中用于序列化的主要类,因此我们需要创建它的一个实例
XmlMapper mapper = new XmlMapper();
这个mapper 在jackson-dataformat-xml jar 中可用,因此我们需要将其作为依赖项添加到我们的pom.xml 中
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.1</version>
</dependency>
请检查 jackson-dataformat-xml 依赖项的最新版本 在 Maven 仓库中。
3. 将 Java 序列化为 XML
XmlMapper 是ObjectMapper 的子类,后者用于 JSON 序列化;但是,它为父类添加了一些 XML 特定的调整。
让我们看看如何使用它来进行实际的序列化。首先创建一个 Java 类
class SimpleBean {
private int x = 1;
private int y = 2;
//standard setters and getters
}
3.1. 序列化为 XML String
我们可以将 Java 对象序列化为 XML String
@Test
public void whenJavaSerializedToXmlStr_thenCorrect() throws JsonProcessingException {
XmlMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValueAsString(new SimpleBean());
assertNotNull(xml);
}
结果如下:
<SimpleBean>
<x>1</x>
<y>2</y>
</SimpleBean>
3.2. 序列化为 XML 文件
我们也可以将 Java 对象序列化为 XML 文件
@Test
public void whenJavaSerializedToXmlFile_thenCorrect() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.writeValue(new File("simple_bean.xml"), new SimpleBean());
File file = new File("simple_bean.xml");
assertNotNull(file);
}
下面可以看到名为simple_bean.xml 的结果文件的内容
<SimpleBean>
<x>1</x>
<y>2</y>
</SimpleBean>
4. 将 XML 反序列化为 Java
在本节中,我们将学习如何从 XML 获取 Java 对象。
4.1. 从 XML String 反序列化
与序列化一样,我们也可以将 XML String 反序列化回 Java 对象
@Test
public void whenJavaGotFromXmlStr_thenCorrect() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
SimpleBean value
= xmlMapper.readValue("<SimpleBean><x>1</x><y>2</y></SimpleBean>", SimpleBean.class);
assertTrue(value.getX() == 1 && value.getY() == 2);
}
4.2. 从 XML 文件反序列化
同样,如果我们有一个 XML 文件,我们可以将其转换回 Java 对象。
@Test
public void whenJavaGotFromXmlFile_thenCorrect() throws IOException {
File file = new File("simple_bean.xml");
XmlMapper xmlMapper = new XmlMapper();
SimpleBean value = xmlMapper.readValue(file, SimpleBean.class);
assertTrue(value.getX() == 1 && value.getY() == 2);
}
5. 处理首字母大写的元素
在本节中,我们将讨论如何处理以下场景:我们既有包含首字母大写元素的 XML 进行反序列化,或者我们需要将 Java 对象序列化为包含一个或多个首字母大写元素的 XML。
5.1. 从 XML String 反序列化
假设我们有一个包含一个字段首字母大写的 XML
<SimpleBeanForCapitalizedFields>
<X>1</X>
<y>2</y>
</SimpleBeanForCapitalizedFields>
为了正确处理首字母大写的元素,我们需要使用@JsonProperty 注解来标注“x”字段
class SimpleBeanForCapitalizedFields {
@JsonProperty("X")
private int x = 1;
private int y = 2;
// standard getters, setters
}
现在我们可以正确地将 XML String 反序列化回 Java 对象
@Test
public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
SimpleBeanForCapitalizedFields value
= xmlMapper.readValue(
"<SimpleBeanForCapitalizedFields><X>1</X><y>2</y></SimpleBeanForCapitalizedFields>",
SimpleBeanForCapitalizedFields.class);
assertTrue(value.getX() == 1 && value.getY() == 2);
}
5.2. 序列化为 XML String
通过用@JsonProperty 注解标注所需的字段,我们可以正确地将 Java 对象序列化为包含一个或多个首字母大写元素的 XML String
@Test
public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect()
throws IOException {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"),
new SimpleBeanForCapitalizedFields());
File file = new File("target/simple_bean_capitalized.xml");
assertNotNull(file);
}
6. 将 List 序列化为 XML
XmlMapper 能够将整个 Java bean 序列化为文档。要将 Java 对象转换为 XML,我们将使用一个带有嵌套对象和数组的简单示例。
我们的目标是将一个Person 对象及其组合的Address 对象序列化为 XML。
我们最终的 XML 将如下所示:
<Person>
<firstName>Rohan</firstName>
<lastName>Daye</lastName>
<phoneNumbers>
<phoneNumbers>9911034731</phoneNumbers>
<phoneNumbers>9911033478</phoneNumbers>
</phoneNumbers>
<address>
<streetName>Name1</streetName>
<city>City1</city>
</address>
<address>
<streetName>Name2</streetName>
<city>City2</city>
</address>
</Person>
请注意,我们的电话号码被封装在phoneNumbers 包装器中,而我们的地址没有被封装。
我们可以通过在Person 类中使用@JacksonXMLElementWrapper 注解来表达这种细微差别
public final class Person {
private String firstName;
private String lastName;
private List<String> phoneNumbers = new ArrayList<>();
@JacksonXmlElementWrapper(useWrapping = false)
private List<Address> address = new ArrayList<>();
//standard setters and getters
}
实际上,我们可以使用@JacksonXmlElementWrapper(localName = ‘phoneNumbers’) 更改包装元素名称。或者,如果我们不想包装我们的元素,我们可以使用@JacksonXmlElementWrapper(useWrapping = false) 禁用映射。
然后我们将定义我们的Address 类型
public class Address {
String streetName;
String city;
//standard setters and getters
}
Jackson 会为我们处理剩下的事情。 像以前一样,我们可以简单地再次调用writeValue
private static final String XML = "<Person>...</Person>";
@Test
public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
Person person = testPerson(); // test data
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
xmlMapper.writeValue(byteArrayOutputStream, person);
assertEquals(XML, byteArrayOutputStream.toString());
}
7. 将 XML 反序列化为List
Jackson 也可以读取包含对象列表的 XML。
如果我们使用之前相同的 XML,readValue 方法也能很好地工作
@Test
public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
Person value = xmlMapper.readValue(XML, Person.class);
assertEquals("City1", value.getAddress().get(0).getCity());
assertEquals("City2", value.getAddress().get(1).getCity());
}
8. 结论
这篇简短的文章展示了如何将一个简单的 POJO 序列化为 XML,以及如何从基本的 XML 数据中获取一个 POJO。
我们还探讨了如何序列化和反序列化包含集合的复杂 bean。
支持本文的代码可在 GitHub 上获取。 一旦你以 Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。















