JacksonでXMLをJavaオブジェクトに変換する

はじめに

エキサイト株式会社 21卒 バックエンドエンジニアの山縣です。 既存サービスのリビルドするにあたり、外部APIを呼び出してXMLを取得してJavaオブジェトに変換する処理を書きました。 Jacksonを使用したXMLJavaオブジェクト変換についての記事は少なかったため本記事にて紹介します。

導入

本記事で使用するサンプルのXMLとそれに対応するJavaクラスです。

サンプルで使用したXML

<Response>
    <ItemList>
        <Item id="a123" name="orange"/>
        <Item id="b234" name="lemon"/>
        <Item id="c345" name="apple"/>
    </ItemList>
    
    <ResultList>
        <Result num="1">オレンジ</Result>
        <Result num="2">レモン</Result>
        <Result num="3">リンゴ</Result>
    </ResultList>
</Response>

XMLに対応するJavaのクラス

package com.example.demo.model;

import java.util.List;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import lombok.Data;

@Data
@JacksonXmlRootElement(localName = "Response")
public class Basket {
    @JacksonXmlProperty(localName = "ItemList")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Item> items;

    @JacksonXmlProperty(localName = "ResultList")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Result> results;

    @Data
    public static class Item {
        @JacksonXmlProperty(isAttribute = true)
        private String id;
        @JacksonXmlProperty(isAttribute = true)
        private String name;
    }

    @Data
    public static class Result {
        @JacksonXmlProperty(isAttribute = true)
        private Integer num;
        @JacksonXmlText
        private String text;
    }
}

XMLのルートの下からマッピングする

XMLのルートの下からマッピングするには、@JacksonXmlRootElementを付与する必要があります。

@JacksonXmlRootElement(localName = "Response")
public class Basket { ... }

XMLのリストをマッピングする

XMLのリストをマッピングするには、下記2つのアノテーションが必要です。

@JacksonXmlProperty(localName = "ResultList")
@JacksonXmlElementWrapper(useWrapping = false)
private List<Result> results;

@JacksonXmlElementWrapperは、useWrappingの他にlocalNameも設定できます。 このとき、@JacksonXmlPropertyを消して、@JacksonXmlElementWrapper(useWrapping = false, localName = "ResultList") と書くと動作するように見えますが、UnrecognizedPropertyExceptionとなってしまいマッピングすることができませんでした。 そのため、上記のように2つのアノテーションを記述しなくてはなりません。

RestTemplateでXMLJavaオブジェクトの変換をする

最後に、下記のように記述することで、外部APIから取得したXMLJavaオブジェクトの変換を実現することができます。

final ResponseEntity<Basket> response = restTemplate
    .exchange(
        "http://example.com",
        HttpMethod.GET,
        httpEntity,
        Basket.class
);

おわりに

Jacksonを使用したXMLJavaオブジェクト変換についてまとめました。 JSONJavaオブジェクトの記事は数多くありますが、XMLJavaオブジェクトの記事はあまり見当たらなかったので、 XMLの変換で困っている人の助けになれば幸いです!