Rec-02: レコードのシリアライズ・JSON 変換
Java の record を JSON に変換・復元する実践的なパターンを解説します。 Pure Java による手動変換と、実務でよく使われるJacksonライブラリを使う方法の両方を紹介します。
record のシリアライズとは
「シリアライズ」とは、オブジェクトをバイト列や文字列(JSON など)に変換して保存・転送できるようにすることです。 API のレスポンスを JSON として返す場面や、セッション情報をファイルに保存する場面でよく使います。
主な変換パターン
- JSON 変換(テキスト形式): Web API のレスポンスや設定ファイルへの書き込みに使います
- バイナリシリアライズ(バイト形式): Java 標準の
ObjectOutputStream/ObjectInputStreamを使います。Serializableの実装が必要です
Java バージョンごとの違い
- Java 8: record が使えないため、不変クラスで同等の実装を手書きします
- Java 17: record を使って DTO を1行で定義できます。バイナリシリアライズには
Serializableの明示的な implements が必要です - Java 21: sealed interface と record を組み合わせ、switch パターンマッチングで型安全な JSON 変換ができます
サンプルコード
Java 8 では record が使えないため、不変クラス(final フィールド + final クラス)で同等の実装を行います。JSON 変換は文字列結合で手動対応します。実務では Jackson などのライブラリを使うことが一般的です。
よくあるミス・注意点
⚠️ record は Serializable を implements しないとバイナリシリアライズできない
record は自動的に Serializable を実装しません。ObjectOutputStream でシリアライズしようとするとNotSerializableException が発生します。 バイナリシリアライズが必要な場合は record UserDto(...) implements Serializable のように明示的に追加してください。
⚠️ 手動 JSON 変換は特殊文字のエスケープ処理が必要
文字列結合で JSON を手動生成する場合、値に "(ダブルクォート)や\(バックスラッシュ)が含まれると不正な JSON になります。 実務では Jackson や Gson などのライブラリを使うと、エスケープ処理を自動で行ってくれます。 Pure Java の手動変換は学習用・シンプルな DTO 限定と考えてください。
⚠️ record のアクセサメソッドは get なし形式(Java 17+)
Java 17+ の record では user.getId() ではなくuser.id() がアクセサ名です。 Jackson でデフォルト設定のまま record を JSON 変換しようとすると、get なしのアクセサを認識できずプロパティが空になることがあります。 Jackson 2.12 以降は record に対応していますが、古いバージョンでは @JsonProperty アノテーションが必要です。
テストする観点
- 手動 JSON 変換で
toJson()が正しい JSON 文字列({"id":"U001","name":"田中太郎","age":30})を返すこと - バイナリシリアライズ → デシリアライズを経ても、元のオブジェクトと
equals()が成立すること Serializableを implements していない record をObjectOutputStreamに渡すとNotSerializableExceptionが発生すること- Java 21 の sealed record で全バリアント(Circle / Rectangle / Triangle)が JSON 変換されること
- 値に特殊文字(ダブルクォートなど)が含まれる場合の変換結果が正しいこと(境界値)