Java : Jackson : ちょっと特殊なケースにおけるJSONシリアライズ/デシリアライズ

こんにちは。松本です。
この記事は TECHSCORE Advent Calendar 2016 の 18 日目の記事です。

6 月頃に書いた記事(「Java : Jackson による JSON デシリアライズ時の型解決方法」)に続いてまた Jackson ネタです。

ここ数年、REST サービスの開発や NoSQL やオブジェクトストレージ利用によって、データシリアライズに JSON を使うことが多くなりました。その分、アプリケーション内で扱うモデルオブジェクトと JSON のマッピングで苦労することも多くなりました。

Jackson はオブジェクトと JSON のマッピング方法が柔軟で多機能なのですが、意外と知られていない機能もあるので、そういったものをピックアップして記事にしようと思います。

@JsonAnyGetter

@JsonAnyGetter アノテーションを使うことで Map 型プロパティのエントリをフラットに並べることができます。

通常、こんなクラスをシリアライズすると extensions プロパティが object 型のプロパティとして表現されます。

シリアライズしてみます。

クラス定義通り、JSON 上でも extensions プロパティ以下に key1, key2 が並んでいます。

extensions プロパティの Getter に @JsonAnyGetter を付けてシリアライズすると結果が変わります。

先ほどのシリアライズ結果では extensions プロパティ以下に出力された key1, key2 が、name プロパティと同レベルで展開されています。

なお、@JsonAnyGetter アノテーションは Map 型プロパティにしか使えず、ひとつのクラスに複数の @JsonAnyGetter アノテーションをつけることはできません。

@JsonAnySetter

実は上記のように @JsonAnyGetter アノテーションを付けたクラスはデシリアライズに失敗します。

Bean1 クラスには key1 や key2 というプロパティが存在しないのでデシリアライズできないのです。そこで @JsonAnySetter の登場です。

下記コードのようにプロパティ名と値を受け取るメソッドを追加し、@JsonAnySetter アノテーションを付けます。

こうすることで、存在しないプロパティが全て @JsonAnySetter が付いたメソッドに渡され、処理されるようになります。

@JsonView

@JsonView を使うことでビュー(JSON に出力するプロパティのサブセット)の定義が可能になります。

まずはビューの定義。

ビューを表す 3 つのクラス、GroupA, GroupB, GroupC を定義しています。GroupB は GroupA のサブクラスとして定義している点が本サンプルコードのポイントです。

これらを使ってプロパティのサブセットを定義します。

Bean2 クラスが持つ 4 つのプロパティのうち、name, type, description の 3 つのプロパティに @JsonView アノテーションを付けました。@JsonView アノテーションにビューを表すクラスを与えることで、対象プロパティがビューのメンバーであることを示しています。

シリアライズしてみます。まずはビューを指定しないケース。

期待通り 4 つのプロパティすべてが出力されました。

次は GroupA を指定してシリアライズ。

@JsonView アノテーションで GroupA を指定した name プロパティと、@JsonView アノテーションをつけなかった value プロパティが出力されました。

最後に GroupB を指定してシリアライズします。

ビュー GroupB に含まれるプロパティ type と、@JsonView アノテーションをつけなかった value プロパティに加え、GroupA に含まれるプロパティ name も出力されています。これは、GroupB が GroupA のサブクラスであるためです。

まとめ

JavaBeans の「プロパティ」に対応する JSON の用語は何なのでしょう。

今回の記事ではキャッチーに「プロパティ」と書いてはみましたが、RFC の 4. Objects を見るとこう書かれているので「メンバー」でいいのかな。

An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members).

Comments are closed, but you can leave a trackback: Trackback URL.