XML Serialization and Deserialization with Jackson – 用Jackson进行XML序列化和反序列化

最后修改: 2016年 5月 22日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll learn how to serialize Java objects to XML data using Jackson 2.x, and deserialize them back to a POJO.

在本教程中,我们将学习如何使用Jackson 2.x将Java对象序列化为XML数据,并将其反序列化为POJO

We’ll focus on the basic operation that doesn’t require a lot of complexity or customization.

我们将专注于不需要太多复杂或定制的基本操作。

2. XmlMapper Object

2.XmlMapper 对象

XmlMapper is the main class from Jackson 2.x that helps us in serialization, so we’ll need to create an instance of it:

XmlMapper 是Jackson 2.x的主类,它帮助我们进行序列化,所以我们需要创建一个它的实例。

XmlMapper mapper = new XmlMapper();

This mapper is available in the jackson-dataformat-xml jar, so we have to add it as a dependency to our pom.xml:

这个映射器jackson-dataformat-xml jar中可用,所以我们必须把它作为一个依赖项添加到我们的pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.11.1</version>
</dependency>

Please check the latest version of the jackson-dataformat-xml dependency in the Maven repository.

请检查Maven仓库中jackson-dataformat-xml依赖项的最新版本

3. Serialize Java to XML

3.将Java序列化为XML

XmlMapper is a subclass of ObjectMapper, which is used in JSON serialization; however, it adds some XML specific tweaks to the parent class.

XmlMapperObjectMapper的子类,用于JSON序列化;然而,它为父类增加了一些XML的具体调整。

Let’s look at how to use it to do the actual serialization. Let’s create a Java class first:

让我们来看看如何使用它来进行实际的序列化。让我们先创建一个Java类。

class SimpleBean {
    private int x = 1;
    private int y = 2;
    
    //standard setters and getters
}

3.1. Serialize to the XML String

3.1.序列化为XML的字符串

We can serialize our Java object into the XML String:

我们可以将我们的Java对象序列化为XML的String

@Test
public void whenJavaSerializedToXmlStr_thenCorrect() throws JsonProcessingException {
    XmlMapper xmlMapper = new XmlMapper();
    String xml = xmlMapper.writeValueAsString(new SimpleBean());
    assertNotNull(xml);
}

As a result, we’ll get:

结果是,我们会得到。

<SimpleBean>
    <x>1</x>
    <y>2</y>
</SimpleBean>

3.2. Serialize to the XML File

3.2.序列化为XML文件

We can also serialize our Java object to the XML file:

我们也可以将我们的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);
}

And below we can see the content of the resulting file named simple_bean.xml:

下面我们可以看到生成的名为simple_bean.xml的文件内容。

<SimpleBean>
    <x>1</x>
    <y>2</y>
</SimpleBean>

4. Deserialize XML to Java

4.将XML反序列化为Java

In this section, we’ll look at how to obtain Java objects from XML.

在这一节中,我们将看看如何从XML中获取Java对象。

4.1. Deserialize From the XML String

4.1.从XML字符串中反序列化

As with serialization, we can also deserialize an XML String back to a Java object:

与序列化一样,我们也可以将一个XML字符串反序列化为一个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. Deserialize From the XML File

4.2.从XML文件中进行反序列化

Likewise, if we have an XML file, we can convert it back to a Java object.

同样地,如果我们有一个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. Handling Capitalised Elements

5.处理大写的元素

In this section, we’ll discuss how to handle scenarios where we either have XML with capitalized elements to deserialize, or we need to serialize Java objects to XML with one or more elements capitalized.

在这一节中,我们将讨论如何处理这样的情景:我们有带大写元素的XML需要反序列化,或者我们需要将Java对象序列化为带一个或多个元素大写的XML。

5.1. Deserialize From the XML String

5.1.从XML中反序列化String

Let’s say we have an XML with one field capitalized:

比方说,我们有一个XML,其中一个字段是大写的。

<SimpleBeanForCapitalizedFields>
    <X>1</X>
    <y>2</y>
</SimpleBeanForCapitalizedFields>

In order to correctly handle capitalized elements, we need to annotate the “x” field with the @JsonProperty annotation:

为了正确处理大写元素,我们需要用@JsonProperty注解来注释 “x “字段。

class SimpleBeanForCapitalizedFields {
    @JsonProperty("X")
    private int x = 1;
    private int y = 2;

    // standard getters, setters
}

We can now correctly deserialize an XML String back to a Java object:

我们现在可以正确地将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. Serialize to the XML String

5.2.序列化为XML字符串

By annotating the required fields with @JsonProperty, we can correctly serialize a Java object into an XML String with one or more capitalized elements:

通过用@JsonProperty注释所需的字段,我们可以正确地将一个Java对象序列化为具有一个或多个大写元素的XMLString

@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. Serialize List to XML

6.List序列化为XML

The XmlMapper is able to serialize an entire Java bean into a document. To convert a Java object to XML, we’ll take a simple example with a nested object and arrays.

XmlMapper能够将整个Java Bean序列化为一个文档。为了将一个Java对象转换为XML,我们将以一个嵌套对象和数组为例进行简单说明。

Our intent is to serialize a Person object, along with its composed Address object, into XML.

我们的目的是将Person对象及其组成的Address对象序列化为XML。

Our final XML will look something like:

我们最终的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>

Notice that our phone numbers are encapsulated in a phoneNumbers wrapper, while our address isn’t.

请注意,我们的电话号码被封装在一个phoneNumbers包装器中,而我们的地址却没有。

We can express this nuance via the @JacksonXMLElementWrapper annotation in our Person class:

我们可以通过@JacksonXMLElementWrapper注解在我们的Person类中表达这一细微差别。

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
}

In fact, we can change the wrapping element name with @JacksonXmlElementWrapper(localName = ‘phoneNumbers’). Or, if we don’t want to wrap our elements, we can disable the mapping with @JacksonXmlElementWrapper(useWrapping = false).

事实上,我们可以用@JacksonXmlElementWrapper(localName = ‘phoneNumbers’)来改变包装元素的名称。或者,如果我们不想包装我们的元素,我们可以用@JacksonXmlElementWrapper(useWrapping = false)禁用映射。

Then we’ll define our Address type:

然后我们将定义我们的地址类型。

public class Address {
    String streetName;
    String city;
    //standard setters and getters
}

Jackson takes care of the rest for us. Like before, we can simply call writeValue again:

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. Deserialize XML to List

7.将XML反序列化为List

Jackson can read XML that contains lists of objects as well.

Jackson也可以读取包含对象列表的XML。

If we take our same XML as before, the readValue method does just fine:

如果我们采取与之前相同的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. Conclusion

8.结论

This brief article illustrated how to serialize a simple POJO to XML, and obtain a POJO from basic XML data.

这篇简短的文章说明了如何将一个简单的POJO序列化为XML,并从基本的XML数据中获得一个POJO。

We also explored how to serialize and deserialize complex beans that contain collections.

我们还探讨了如何对包含集合的复杂Bean进行序列化和反序列化。

The source code that accompanies this article is available on GitHub.

本文所附的源代码可在GitHub上获得。