概要
REST API との連携、設定ファイルの読み書き、ログ出力のフォーマットなど、JSON を扱う場面は業務システムでも増え続けています。Java 標準 API には JSON パーサーが含まれていないため、多くのプロジェクトでは Jackson を使うことになります。ObjectMapper の基本的な使い方は簡単ですが、record との組み合わせ、ネスト構造の安全なアクセス、未知フィールドへの対処など、実務で迷いやすいポイントが散在しています。この記事では、Jackson の ObjectMapper を軸に、シリアライズ・デシリアライズの基本パターンからツリー操作、配列やリストの変換までを整理します。
使いどころ
外部 API のレスポンス JSON を Java オブジェクトにマッピングして業務ロジックで使う
DB から取得したデータを JSON 形式に変換してフロントエンドに返す
設定ファイルやテストデータを JSON 形式で管理し、起動時やテスト時に読み込む
コード例
import com.fasterxml.jackson.annotation.JsonProperty;
public class JsonParsing {
record Person(
@JsonProperty("name") String name,
@JsonProperty("age") int age
) {}
private static final ObjectMapper MAPPER = new ObjectMapper();
public static void main(String[] args) throws Exception {
var person = new Person("山田太郎", 30);
var json = MAPPER.writeValueAsString(person);
System.out.println("JSON: " + json);
var input = """
{"name":"鈴木花子","age":25}
""";
var parsed = MAPPER.readValue(input, Person.class);
System.out.println("オブジェクト: " + parsed);
var nested = """
{"id":1,"address":{"city":"Tokyo","zip":"100-0001"}}
""";
JsonNode root = MAPPER.readTree(nested);
System.out.println("city: " + root.path("address").path("city").asText());
var arrayJson = """
[{"name":"田中","age":20},{"name":"佐藤","age":35}]
""";
var people = List.of(MAPPER.readValue(arrayJson, Person[].class));
people.forEach(p -> System.out.println(" " + p));
}
}Version Coverage
record(Java 16+)で不変なデータクラスとしてマッピングできる。テキストブロックで JSON リテラルを読みやすく記述できる。
// Java 17: record で簡潔にマッピング
record Person(
@JsonProperty("name") String name,
@JsonProperty("age") int age
) {}
var person = MAPPER.readValue(json, Person.class);
var input = """
{"name":"山田","age":30}
""";Library Comparison
注意点
ObjectMapper はスレッドセーフだがインスタンス生成コストが高い。static final で1つだけ作成し、メソッドごとに new しないこと。
デシリアライズ対象クラスにはデフォルトコンストラクタが必要(POJO の場合)。record の場合は @JsonProperty でフィールド名を明示する。
未知のフィールドがあると UnrecognizedPropertyException が発生する。@JsonIgnoreProperties(ignoreUnknown = true) で回避可能。API レスポンスを受ける場合は設定推奨。
JsonNode.get() は存在しないキーで null を返すため NPE のリスクがある。path() を使えば MissingNode が返り安全。
FAQ
インスタンス生成コストが高いため、static final で1つだけ作成してください。ObjectMapper はスレッドセーフです。
Jackson 2.12 以降で record をサポートしています。@JsonProperty でフィールド名を明示するのが確実です。
ObjectMapper.readTree() で JsonNode を取得し、path("key").path("nested").asText() のようにチェーンで辿れます。