JSONからJavaクラス変換
JSONからJava POJOクラスを自動生成
JSON入力
Java出力
JSONからJavaクラスへの変換とは?
JSONからJavaクラスへの変換は、生のJSONオブジェクトからPlain Old Java Object(POJO)定義を生成するプロセスです。生成されるPOJOはプライベートフィールド、getter、setterを持ちます。Javaには組み込みのJSON型システムがないため、JSON APIのレスポンス・設定ファイル・メッセージペイロードをタイプセーフに扱うには、事前に対応するクラス定義が必要です。JacksonやGsonはリフレクションを使ってJSONキーをJavaフィールドにマッピングしますが、いずれもクラス定義が先に存在していることを前提としています。
JSON逆シリアル化用の標準的なJava POJOは、各JSONキーに対するプライベートフィールド、引数なしコンストラクター、フィールドごとのgetter/setterペアを宣言します。ネストされたJSONオブジェクトは別々のクラスになります。配列はjava.util.ListをインポートしたList<T>フィールドになります。プリミティブなJSON型はJavaのプリミティブ型(int、double、boolean)か、ジェネリクス内ではラッパー型(Integer、Double、Boolean)にマッピングされます。null値は通常Objectまたはnullableな参照型にマッピングされます。
これらのクラス定義を手書きするのは繰り返し作業です。各JSONキーを読み取り、値からJavaの型を判断し、命名規則をcamelCaseのJSONからcamelCaseのJavaフィールドに変換し、ネストされたオブジェクトにはPascalCaseのクラス名を付け、getter/setterのボイラープレートを追加する必要があります。フィールドが15個・ネストされたオブジェクトが3つあるJSONオブジェクトなら、4つのクラスと30以上のメソッドを書いてすべての整合性を保つ必要があります。変換ツールはこの作業をミリ秒で完了します。
JSONからJava変換ツールを使う理由
JSONからJava POJOを手動で作成するには、各フィールドの検査・サンプル値からの型推論・getter/setterペアの記述を、ネストされたオブジェクトごとに繰り返す必要があります。APIの仕様が変わればすべて手作業で更新しなければなりません。変換ツールはその機械的な作業を排除します。
JSONからJava変換のユースケース
JSONからJavaへの型マッピング
すべてのJSON値は特定のJava型にマッピングされます。下表は変換ツールが各JSON型をどのようにJavaの対応型に変換するかを示しています。「代替」列にはList<T>のようなジェネリクスのコンテキストで使用されるラッパー型や、RecordなどJavaの新しい機能が示されています。
| JSON型 | 値の例 | Java型 | 代替 |
|---|---|---|---|
| string | "hello" | String | String |
| number (integer) | 42 | int | int / Integer |
| number (float) | 3.14 | double | double / Double |
| boolean | true | boolean | boolean / Boolean |
| null | null | Object | Object (or @Nullable String) |
| object | {"k": "v"} | NestedClass | Record (Java 16+) |
| array of strings | ["a", "b"] | List<String> | List<String> |
| array of objects | [{"id": 1}] | List<Item> | List<Item> |
| mixed array | [1, "a"] | List<Object> | List<Object> |
Java JSONアノテーションリファレンス
JacksonまたはGsonでJSONを逆シリアル化する際、アノテーションはJSONキーのJavaフィールドへのマッピング・未知フィールドの処理・null値の扱い方を制御します。このリファレンスは生成されたPOJOを使用する際によく使われるアノテーションをまとめています。
| アノテーション | 用途 | ライブラリ |
|---|---|---|
| @JsonProperty("name") | Maps a JSON key to a Java field with a different name | Jackson |
| @SerializedName("name") | Same as @JsonProperty, but for the Gson library | Gson |
| @JsonIgnoreProperties | Ignores unknown JSON keys during deserialization instead of failing | Jackson |
| @Nullable | Marks a field as accepting null values from JSON input | JSR 305 / JetBrains |
| @NotNull | Enforces that a field must not be null, throws on violation | Bean Validation |
| @JsonFormat(pattern=...) | Defines a date/time format for serialization and deserialization | Jackson |
POJO vs Record vs Lombok
Javaにはゃ型付き構造を定義してJSONデータを保持する一般的なアプローチが3つあります。それぞれプロジェクトのスタイルとJavaのバージョンに応じて適した選択肢があります。POJOは最も広い互換性を持つ従来のパターンです。Recordはイミュータブルなデータのボイラープレートを削減します。Lombokはアノテーションを通じてコンパイル時にgetter・setter・コンストラクターを生成します。
コード例
以下の例は、生成されたJava POJOをJacksonを使って逆シリアル化する方法、JavaScriptとPythonからプログラムでJavaクラスを生成する方法、そしてバッチ生成にjsonschema2pojo CLIツールを使用する方法を示しています。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private int id;
private String name;
private String email;
private boolean active;
private double score;
private Address address;
private List<String> tags;
// getters and setters omitted for brevity
public static void main(String[] args) throws Exception {
String json = "{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@example.com\",\"active\":true,\"score\":98.5,\"address\":{\"street\":\"123 Main St\",\"city\":\"Springfield\",\"zip\":\"12345\"},\"tags\":[\"admin\",\"user\"]}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println(user.getName()); // -> Alice
}
}
class Address {
private String street;
private String city;
private String zip;
// getters and setters
}// Minimal JSON-to-Java-POJO generator in JS
function jsonToJava(obj, name = "Root") {
const classes = [];
function infer(val, fieldName) {
if (val === null) return "Object";
if (typeof val === "string") return "String";
if (typeof val === "number") return Number.isInteger(val) ? "int" : "double";
if (typeof val === "boolean") return "boolean";
if (Array.isArray(val)) {
const first = val.find(v => v !== null);
if (!first) return "List<Object>";
const elem = infer(first, fieldName);
const boxed = elem === "int" ? "Integer" : elem === "double" ? "Double" : elem === "boolean" ? "Boolean" : elem;
return `List<${boxed}>`;
}
if (typeof val === "object") {
const cls = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
build(val, cls);
return cls;
}
return "Object";
}
function build(obj, cls) {
const fields = Object.entries(obj).map(([k, v]) => {
const type = infer(v, k);
return ` private ${type} ${k};`;
});
classes.push(`public class ${cls} {\n${fields.join("\n")}\n}`);
}
build(obj, name);
return classes.join("\n\n");
}
console.log(jsonToJava({ id: 1, name: "Alice", scores: [98, 85] }, "User"));
// public class User {
// private int id;
// private String name;
// private List<Integer> scores;
// }import json
def json_to_java(obj: dict, class_name: str = "Root") -> str:
classes = []
def infer(val, name):
if val is None:
return "Object"
if isinstance(val, bool):
return "boolean"
if isinstance(val, int):
return "int"
if isinstance(val, float):
return "double"
if isinstance(val, str):
return "String"
if isinstance(val, list):
if not val:
return "List<Object>"
elem = infer(val[0], name)
boxed = {"int": "Integer", "double": "Double", "boolean": "Boolean"}.get(elem, elem)
return f"List<{boxed}>"
if isinstance(val, dict):
cls = name[0].upper() + name[1:]
build(val, cls)
return cls
return "Object"
def build(obj, cls):
fields = [f" private {infer(v, k)} {k};" for k, v in obj.items()]
classes.append(f"public class {cls} {{\n" + "\n".join(fields) + "\n}")
build(obj, class_name)
return "\n\n".join(classes)
data = json.loads('{"id": 1, "name": "Alice", "tags": ["admin"]}')
print(json_to_java(data, "User"))
# public class User {
# private int id;
# private String name;
# private List<String> tags;
# }# Install jsonschema2pojo (requires Java 8+)
# Download from https://github.com/joelittlejohn/jsonschema2pojo
# Generate POJOs from a JSON file
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style jackson2
# Generate with Gson annotations instead
jsonschema2pojo --source user.json --target src/main/java \
--source-type json --annotation-style gson
# From a JSON string via stdin
echo '{"id": 1, "name": "Alice", "tags": ["admin"]}' | \
jsonschema2pojo --source-type json --annotation-style jackson2 \
--target src/main/java --target-package com.example.model