JSON به Java
تولید کلاسهای Java POJO از JSON
ورودی JSON
خروجی Java
تبدیل JSON به کلاس Java چیست؟
تبدیل JSON به کلاس Java یک شیء JSON خام را دریافت میکند و تعاریف Plain Old Java Object (POJO) با فیلدهای خصوصی، getter و setter تولید میکند. Java سیستم نوع داخلی برای JSON ندارد، بنابراین هر پاسخ API، فایل پیکربندی یا پیلود پیام JSON به یک کلاس متناظر نیاز دارد تا بتوانید بهصورت ایمن از نظر نوع با آن کار کنید. کتابخانههایی مانند Jackson و Gson از طریق reflection کلیدهای JSON را به فیلدهای Java نگاشت میکنند، اما ابتدا به وجود تعاریف کلاس نیاز دارند.
یک Java POJO استاندارد برای deserialize کردن JSON یک فیلد خصوصی برای هر کلید JSON، یک constructor بدون آرگومان، و یک جفت getter/setter به ازای هر فیلد تعریف میکند. اشیاء JSON تودرتو به کلاسهای جداگانه تبدیل میشوند. آرایهها به فیلدهای List<T> با import از java.util.List تبدیل میشوند. نوعهای اولیه JSON به نوعهای اولیه Java (int، double، boolean) یا نوعهای wrapper آنها (Integer، Double، Boolean) هنگام استفاده در generics نگاشت میشوند. مقادیر null معمولاً به Object یا یک نوع مرجع nullable نگاشت میشوند.
نوشتن این تعاریف کلاس بهصورت دستی تکراری است. باید هر کلید JSON را بخوانید، نوع Java را از مقدار تشخیص دهید، قراردادهای نامگذاری از camelCase JSON به فیلدهای camelCase Java را اعمال کنید، نامهای PascalCase برای اشیاء تودرتو بسازید، و boilerplate getter/setter اضافه کنید. برای یک شیء JSON با ۱۵ فیلد و ۳ شیء تودرتو، این یعنی نوشتن ۴ کلاس، بیش از ۳۰ متد، و حفظ یکپارچگی همه چیز. یک مبدل این کار را در چند میلیثانیه انجام میدهد.
چرا از مبدل JSON به Java استفاده کنیم؟
ایجاد دستی Java POJO از JSON یعنی باید هر فیلد را بررسی کنید، نوع را از مقادیر نمونه تشخیص دهید، جفتهای getter/setter بنویسید، و این فرایند را برای هر شیء تودرتو تکرار کنید. وقتی قرارداد API تغییر میکند، باید همه چیز را بهصورت دستی بهروزرسانی کنید. یک مبدل این کار مکانیکی را حذف میکند.
موارد استفاده JSON به Java
جدول نگاشت نوع JSON به Java
هر مقدار JSON به یک نوع Java خاص نگاشت میشود. جدول زیر نشان میدهد چگونه مبدل هر نوع JSON را به معادل Java ترجمه میکند. ستون Alternative نوعهای wrapper مورد استفاده در زمینههای generic مانند List<T>، یا ویژگیهای جدیدتر Java مانند 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> |
مرجع annotation های JSON در Java
هنگام deserialize کردن JSON با Jackson یا Gson، annotation ها کنترل میکنند که کلیدهای JSON چگونه به فیلدهای Java نگاشت شوند، فیلدهای ناشناخته چگونه مدیریت شوند، و مقادیر null چگونه رفتار کنند. این مرجع annotation هایی را پوشش میدهد که هنگام کار با POJO های تولیدشده بیشتر با آنها مواجه میشوید.
| 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 سه رویکرد رایج برای تعریف ساختارهای typed برای نگهداشتن داده JSON دارد. هر کدام با سبک پروژه و نسخه Java متفاوتی مناسب است. POJO الگوی سنتی با بیشترین سازگاری است. Record ها boilerplate را برای دادههای immutable کاهش میدهند. Lombok در زمان کامپایل از طریق annotation ها getter، setter و constructor تولید میکند.
نمونه کد
این مثالها نشان میدهند چگونه Java POJO های تولیدشده را با Jackson برای deserialize کردن استفاده کنید، چگونه کلاسهای Java را بهصورت برنامهای از JavaScript و Python تولید کنید، و چگونه از ابزار CLI جدید 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