JacksonによるXMLシリアライゼーションとデシリアライゼーション

JacksonによるXMLのシリアル化と逆シリアル化

1. 概要

このチュートリアルでは、how to serialize Java objects to XML data using Jackson 2.x and deserialize it back to a POJOについて見ていきます。

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

2. XmlMapperオブジェクト

XmlMapperは、シリアル化に役立つJackson 2.xのメインクラスであるため、そのインスタンスを作成する必要があります。

XmlMapper mapper = new XmlMapper();

このmapper isはjackson-dataformat-xml jarで利用できるため、pom.xmlへの依存関係として追加する必要があります。


    com.fasterxml.jackson.dataformat
    jackson-dataformat-xml
    2.9.8

ここでthe latest version of Jackson dependencyを確認してください。

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にシリアル化String

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

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

その結果、次のようになります。


    1
    2

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という名前の結果ファイルの内容を示します。


    1
    2

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("12", SimpleBean.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

4.2. XMLファイルから逆シリアル化

同様に、XMLファイルがある場合は、Javaオブジェクトに戻すことができます。

ここでは、最初にファイルを入力ストリームに読み込み、次に簡単なユーティリティメソッドを使用して入力ストリームをStringに変換します。

残りのコードは、セクション4.1のコードに似ています。

@Test
public void whenJavaGotFromXmlFile_thenCorrect() throws IOException {
    File file = new File("simple_bean.xml");
    XmlMapper xmlMapper = new XmlMapper();
    String xml = inputStreamToString(new FileInputStream(file));
    SimpleBean value = xmlMapper.readValue(xml, SimpleBean.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

ユーティリティメソッド:

public String inputStreamToString(InputStream is) throws IOException {
    StringBuilder sb = new StringBuilder();
    String line;
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    while ((line = br.readLine()) != null) {
        sb.append(line);
    }
    br.close();
    return sb.toString();
}

5. 大文字の要素の処理

このセクションでは、デシリアライズする大文字の要素を含むXMLがある場合、または1つ以上の要素を大文字にするXMLにJavaオブジェクトをシリアル化する必要があるシナリオを処理する方法について説明します。

5.1. XMLStringから逆シリアル化

1つのフィールドが大文字のXMLがあるとします。


    1
    2

大文字の要素を正しく処理するには、「x」フィールドに@JsonPropertyアノテーションを付ける必要があります。

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

    // standard getters, setters
}

これで、XMLStringをJavaオブジェクトに正しく逆シリアル化できます。

@Test
public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    SimpleBeanForCapitalizedFields value
      = xmlMapper.readValue(
      "12",
      SimpleBeanForCapitalizedFields.class);
    assertTrue(value.getX() == 1 && value.getY() == 2);
}

5.2. XML文字列にシリアル化する

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

XmlMapperは、JavaBean全体をドキュメントにシリアル化できます。 JavaオブジェクトをXMLに変換するために、ネストされたオブジェクトと配列を使用した簡単な例を取り上げます。

私たちの目的は、Personオブジェクトをその構成されたAddressオブジェクトとともにXMLにシリアル化することです。

最終的なXMLは次のようになります。


    Rohan
    Daye
    
        9911034731
        9911033478
    
    
Name1 City1
Name2 City2

電話番号はphoneNumbersラッパーにカプセル化されていますが、住所はカプセル化されていないことに注意してください。

このニュアンスは、Personクラスの@JacksonXMLElementWrapperアノテーションを介して表現できます。

public final class Person {
    private String firstName;
    private String lastName;
    private List phoneNumbers = new ArrayList<>();
    @JacksonXmlElementWrapper(useWrapping = false)
    private List
address = new ArrayList<>(); //standard setters and getters }

実際には、ラッピング要素名を@JacksonXmlElementWrapper(localName = ‘phoneNumbers').で変更できます。または、要素をラッピングしたくない場合は、@JacksonXmlElementWrapper(useWrapping = false)でマッピングを無効にすることができます。

次に、Address typeを定義しましょう。

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

Jackson takes care of the rest for us.以前と同様に、writeValueを再度呼び出すことができます。

private static final String XML = "...";

@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 methodは問題なく機能します。

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