Help us understand the problem. What is going on with this article?

jacksonで正体不明のJSONを読み込む

More than 5 years have passed since last update.

jacksonで正体不明のJSONを読み込むメモ。

json.orgのライブラリやjsonicあたりだとゆるく読み出せたりもするJSON。

jacksonだと標準では意外とゆるくない。
そこで同様のことを取り回しやすいスタイルのままjacksonで実装してみる。

まずは解析結果を受け取るオブジェクトは次のように。
今回のような状況がきちんと想定されていてアノテーションが用意されている。

(import文などは省略)

UnknownObject.java
public class UnknownObject {
    @JsonIgnore
    private Map<String, Object> anyProperties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getAnyProperties() {
        return this.anyProperties;
    }

    @JsonAnySetter
    public void setAnyProperties(String name, Object value) {
        this.anyProperties.put(name, value);
    }
}

要素を個別に追加したり読み出すメソッドを実装してもよいかもしれない。

実際の解析は次のようにする。
sourceは何かしらJSON形式でパースできるデータ。
読み出した要素数に関係なくListに格納することで後々の扱いを一本化するケースとなる。

ObjectMapper mapper = new ObjectMapper();
List<UnknownObject> jsonlist = new ArrayList<>();
JsonNode node = mapper.readTree(source);
if (node.isArray()) {
    jsonlist.addAll(Arrays.asList(mapper.readValue(node.traverse(), UnknownObject[].class)));
} else {
    jsonlist.add(mapper.readValue(node.traverse(), UnknownObject.class));
}

配列で格納されているかもしれないため先に判定している。意外と忘れがち。
配列か単体かが事前にわかっていればもちろん不要な判定。

ObjectMapperは実際にはインスタンスを使い回すことになるはず。
そうしないとせっかくのjacksonのパフォーマンスを無駄にしてしまう。

この正体不明のデータを受け取る技法はArangoDBのJavaドライバあたりでも使われている。

jacksonはyaml、csvなど他のフォーマットとの相互変換もやりやすいので最近はこればかり使っている。protobufへも対応中らしく楽しみ。

kivatek
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away