ブログに書くつもりじゃなかった

フリーのプログラマーが綴る、裏チラ系の備忘録や雑記帳。

jackson-dataformat-xmlを使ってXMLをデシリアライズ

やりたいこと

前回ダウンロードした都道府県指定文化財データを全件ElasticSearchに登録したい。 その中で、jackson-dataformat-xmlを使ってXMLをJavaBeansにデシリアライズする。

準備

pom.xmlに以下を追記する。

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

公式ドキュメント

https://github.com/FasterXML/jackson-dataformat-xml

Bean

  • @JsonIgnoreProperties(ignoreUnknown = true)で、XMLマッピングする際に、Bean側に対応するフィールドがなくてもエラーを無視できる。今回は自分が使用しないデータは読み捨てたかったので指定。
  • @Datalombokアノテーション
@Data
@JacksonXmlRootElement(localName = "Dataset")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GisData {

    @JacksonXmlProperty(localName = "Point")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Point> points;

    @JacksonXmlProperty(localName = "CulturalProperty")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<CulturalProperty> culturalProperties;

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Point {
        @JacksonXmlProperty(isAttribute = true)
        private String id;
        @JacksonXmlProperty
        private String pos;        
    }
        
    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class CulturalProperty {
        @JacksonXmlProperty(localName = "position")
        private PositionHref positionHref;     
        @JacksonXmlProperty
        private String prefectureCode;
        @JacksonXmlProperty
        private String administrativeAreaCode;
        @JacksonXmlProperty
        private String largeClassificationCode;
        @JacksonXmlProperty
        private String smallClassificationCode;
        @JacksonXmlProperty
        private String culturalPropertyName;
        @JacksonXmlProperty
        private String address;
        @JacksonXmlProperty
        private Long specifiedDate;
        @JacksonXmlProperty
        private String pointClassificationCode;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown=true)
    public static class PositionHref {
        @JacksonXmlProperty(isAttribute = true)
        private String href;
    }

}

シリアライズするコード

ObjectMapper xmlMapper = new XmlMapper();
GisData gisData = xmlMapper.readValue(new File(INPUT_FILE), GisData.class);

Beanの作成で分からなくなったら

いきなりBeanにマッピングしようとして期待する結果が得られず、しばらく悪戦苦闘した。そんな時は一旦readTree()JsonNodeにデシリアライズ、さらにJsonNodewriteValue()シリアライズして中身を確認すると、一気に理解が進んだ。

ObjectMapper xmlMapper = new XmlMapper();
JsonNode jsonNode = xmlMapper.readTree(new File(INPUT_FILE));

objectMapper.writeValue(new File(OUTPUT_XML_FILE), jsonNode);