JSON เป็น Java
สร้าง Java POJO classes จาก JSON
อินพุต JSON
เอาต์พุต Java
การแปลง JSON เป็น Java Class คืออะไร?
การแปลง JSON เป็น Java class คือกระบวนการนำ JSON object ดิบมาสร้างนิยาม Plain Old Java Object (POJO) ที่มี private fields, getters และ setters Java ไม่มีระบบประเภท JSON ในตัว ดังนั้น API response, ไฟล์กำหนดค่า หรือ message payload ทุกรายการจำเป็นต้องมี class ที่ตรงกันก่อน จึงจะทำงานกับข้อมูลได้อย่างปลอดภัยในเชิงประเภท ไลบรารีอย่าง Jackson และ Gson แมป JSON keys กับ Java fields ผ่าน reflection แต่ต้องมีนิยาม class ก่อนเสมอ
Java POJO มาตรฐานสำหรับการ deserialize JSON จะประกาศ private field สำหรับแต่ละ JSON key, constructor ที่ไม่มีพารามิเตอร์ และ getter/setter คู่สำหรับแต่ละ field JSON objects ที่ซ้อนกันจะกลายเป็น classes แยกกัน Arrays จะกลายเป็น fields ประเภท List'<'T'>' พร้อม import ของ java.util.List ประเภทพื้นฐาน JSON แมปกับประเภทพื้นฐานของ Java (int, double, boolean) หรือประเภท wrapper (Integer, Double, Boolean) เมื่อใช้ภายใน generics ค่า null มักแมปกับ Object หรือประเภท reference ที่เป็น nullable
การเขียนนิยาม class เหล่านี้ด้วยมือเป็นงานที่ซ้ำซาก คุณต้องอ่านแต่ละ JSON key กำหนดประเภท Java จากค่า แปลงรูปแบบการตั้งชื่อจาก camelCase JSON เป็น camelCase Java fields สร้างชื่อ class แบบ PascalCase สำหรับ objects ที่ซ้อนกัน และเพิ่ม boilerplate ของ getter/setter สำหรับ JSON object ที่มี 15 fields และ 3 nested objects นั่นหมายถึงการเขียน 4 classes, เมธอดมากกว่า 30 รายการ และต้องรักษาความสอดคล้องทั้งหมด เครื่องมือแปลงทำสิ่งนี้ในเวลาไม่กี่มิลลิวินาที
ทำไมต้องใช้เครื่องมือแปลง JSON เป็น Java?
การสร้าง Java POJOs จาก JSON ด้วยมือหมายถึงการตรวจสอบแต่ละ field อนุมานประเภทจากค่าตัวอย่าง เขียน getter/setter pairs และทำซ้ำสำหรับทุก nested object เมื่อสัญญา API เปลี่ยน คุณต้องอัปเดตทุกอย่างด้วยมือ เครื่องมือแปลงขจัดงานซ้ำซากนั้น
กรณีใช้งาน JSON เป็น Java
ตารางอ้างอิงการแมปประเภท JSON เป็น Java
ค่า JSON ทุกค่าแมปกับประเภท Java เฉพาะเจาะจง ตารางด้านล่างแสดงวิธีที่เครื่องมือแปลงแปลงประเภท JSON แต่ละอย่างเป็นประเภท Java ที่เทียบเท่า คอลัมน์ทางเลือกแสดงประเภท wrapper ที่ใช้ใน generic contexts อย่าง List'<'T'>' หรือ Java features ใหม่กว่าอย่าง Records
| ประเภท 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 Annotation
เมื่อทำการ deserialize JSON ด้วย Jackson หรือ Gson annotations จะควบคุมวิธีที่ JSON keys แมปกับ Java fields วิธีจัดการ fields ที่ไม่รู้จัก และวิธีที่ค่า null ถูกจัดการ การอ้างอิงนี้ครอบคลุม annotations ที่คุณจะพบบ่อยที่สุดเมื่อทำงานกับ POJOs ที่สร้างขึ้น
| Annotation | วัตถุประสงค์ | ไลบรารี |
|---|---|---|
| @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 กับ Record กับ Lombok
Java มีสามแนวทางทั่วไปสำหรับการกำหนดโครงสร้างประเภทที่ใช้เก็บข้อมูล JSON แต่ละแนวทางเหมาะกับสไตล์โปรเจกต์และเวอร์ชัน Java ที่แตกต่างกัน POJOs คือรูปแบบดั้งเดิมที่มีความเข้ากันได้กว้างที่สุด Records ลด boilerplate สำหรับข้อมูลที่ไม่เปลี่ยนแปลง Lombok สร้าง getters, setters และ constructors ณ compile time ผ่าน annotations
ตัวอย่างโค้ด
ตัวอย่างเหล่านี้แสดงวิธีใช้ Java POJOs ที่สร้างขึ้นกับ Jackson สำหรับการ deserialize วิธีสร้าง Java classes ด้วยโปรแกรมจาก JavaScript และ Python และวิธีใช้ CLI tool ของ jsonschema2pojo สำหรับการสร้างแบบกลุ่ม
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