jacksonで正体不明のJSONを読み込むメモ。
json.orgのライブラリやjsonicあたりだとゆるく読み出せたりもするJSON。
jacksonだと標準では意外とゆるくない。
そこで同様のことを取り回しやすいスタイルのままjacksonで実装してみる。
まずは解析結果を受け取るオブジェクトは次のように。
今回のような状況がきちんと想定されていてアノテーションが用意されている。
(import文などは省略)
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へも対応中らしく楽しみ。