1. 概要

このチュートリアルでは、Jackson 2.xを使用してオブジェクトをXMLデータにシリアル化し、POJOに逆シリアル化する方法を学習します。

複雑さやカスタマイズをあまり必要としない基本的な操作に焦点を当てます。

2. XmlMapperオブジェクト

XmlMapperはJackson2.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:

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

Mavenリポジトリの最新バージョンのjackson-dataformat-xml依存関係を確認してください。

3. JavaをXMLにシリアル化する

XmlMapper は、JSONシリアル化で使用される ObjectMapper、のサブクラスです。 ただし、親クラスにXML固有の微調整がいくつか追加されます。

実際のシリアル化を行うためにそれを使用する方法を見てみましょう。 最初にJavaクラスを作成しましょう。

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

3.1. XMLにシリアル化文字列

JavaオブジェクトをXMLStringにシリアル化できます。

@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);
}

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

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

4. XMLをJavaに逆シリアル化します

このセクションでは、XMLからJavaオブジェクトを取得する方法を見ていきます。

4.1. XML文字列から逆シリアル化

シリアル化と同様に、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. 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がある場合、または1つ以上の要素が大文字のXMLにJavaオブジェクトをシリアル化する必要があるシナリオを処理する方法について説明します。

5.1. XMLからの逆シリアル化文字列

1つのフィールドが大文字になっている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:

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文字列にシリアル化する

必須フィールドに@JsonProperty、で注釈を付けることにより、Javaオブジェクトを1つ以上の大文字の要素を持つ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. リストをXMLにシリアル化

The XmlMapper is able to serialize an entire Java bean into a document. 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>

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

このニュアンスは、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)

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:

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をリストに逆シリアル化します

Jacksonは、オブジェクトのリストを含むXMLも読み取ることができます。

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

@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で入手できます。