JSON เป็น Python
สร้าง Python dataclasses จาก JSON
อินพุต JSON
เอาต์พุต Python
การแปลง JSON เป็น Python Dataclass คืออะไร?
การแปลง JSON เป็น Python dataclass รับ JSON object ดิบแล้วสร้างชุดนิยาม Python dataclass พร้อม type annotations ที่ถูกต้อง โมดูล dataclasses ของ Python ที่เปิดตัวใน PEP 557 (Python 3.7) สร้าง method __init__, __repr__ และ __eq__ จาก class fields ที่มี annotations เมื่อทำงานกับ JSON APIs, configuration files หรือ message queues dataclasses ให้โครงสร้างข้อมูลแบบมีประเภทที่ editor และ type checkers อย่าง mypy สามารถตรวจสอบได้ในช่วงพัฒนา
json.loads() ของ Python คืนค่า dicts และ lists ธรรมดา ใช้งานได้แต่ไม่มีข้อมูลประเภท: key ที่พิมพ์ผิดจะคืนค่า None แทนที่จะเกิด error และ editor ไม่สามารถ autocomplete ชื่อ field ได้ Dataclasses แก้ปัญหานี้โดยแมป JSON key แต่ละตัวไปยัง field ที่มีชื่อและประเภทชัดเจน JSON objects ที่ซ้อนกันกลายเป็นนิยาม dataclass แยกกัน arrays กลายเป็น annotations ประเภท List[T] และค่า null กลายเป็น Optional[T] ที่มีค่าเริ่มต้นเป็น None
การเขียนนิยามเหล่านี้ด้วยมือเป็นงานที่ซ้ำซาก คุณต้องอ่าน JSON หาประเภทของแต่ละ field จากค่าของมัน แปลง keys จาก camelCase หรือ snake_case ให้ตรงกับแนวทาง Python และจัดการ edge cases อย่าง nullable fields และ arrays ที่มีประเภทผสม เครื่องมือแปลงทำทั้งหมดนี้ในเวลาไม่กี่ milliseconds คุณวาง JSON รับโค้ด dataclass ที่ถูกต้อง แล้วดำเนินการต่อได้เลย
ทำไมต้องใช้เครื่องมือแปลง JSON เป็น Python?
การแปลงโครงสร้าง JSON เป็น Python class definitions ด้วยมือหมายถึงการเดาประเภทจาก sample data เรียงลำดับ fields ให้ fields ที่จำเป็นมาก่อน optional fields และอัปเดตทุกอย่างเมื่อ API เปลี่ยน เครื่องมือแปลงกำจัดความยุ่งยากเหล่านั้น
กรณีใช้งาน JSON เป็น Python
ตารางการแมปประเภท JSON เป็น Python
ค่า JSON ทุกค่าแมปกับ Python type annotation เฉพาะ ตารางด้านล่างแสดงวิธีที่เครื่องมือแปล JSON type แต่ละอย่าง ทั้งไวยากรณ์โมดูล typing (Python 3.7+) และไวยากรณ์ built-in ที่ใช้ได้ตั้งแต่ Python 3.10 เป็นต้นไป
| ประเภท JSON | ตัวอย่าง | Python (typing) | Python 3.10+ |
|---|---|---|---|
| string | "hello" | str | str |
| number (integer) | 42 | int | int |
| number (float) | 3.14 | float | float |
| boolean | true | bool | bool |
| null | null | Optional[str] | str | None |
| object | {"k": "v"} | @dataclass class | nested model |
| array of strings | ["a", "b"] | List[str] | list[str] |
| array of objects | [{"id": 1}] | List[Item] | list[Item] |
| mixed array | [1, "a"] | List[Any] | list[Any] |
อ้างอิง Dataclass Decorator
decorator @dataclass รับพารามิเตอร์หลายตัวที่เปลี่ยนพฤติกรรมของ class ที่สร้างขึ้น เอกสารอ้างอิงนี้ครอบคลุมตัวเลือกที่เกี่ยวข้องมากที่สุดเมื่อทำงานกับข้อมูลที่มาจาก JSON
| Decorator / Field | พฤติกรรม | ใช้เมื่อ |
|---|---|---|
| @dataclass | Generates __init__, __repr__, __eq__ from field annotations | Standard dataclasses |
| @dataclass(frozen=True) | Makes instances immutable (hashable, no attribute reassignment) | Config objects, dict keys |
| @dataclass(slots=True) | Uses __slots__ for lower memory and faster attribute access | Python 3.10+, large datasets |
| @dataclass(kw_only=True) | All fields require keyword arguments in __init__ | Python 3.10+, many fields |
| field(default_factory=list) | Sets a mutable default without sharing state between instances | List/dict/set defaults |
dataclass กับ Pydantic กับ TypedDict
Python มีสามวิธีที่นิยมในการกำหนดโครงสร้างที่มีประเภทจาก JSON แต่ละวิธีเหมาะกับกรณีใช้งานที่แตกต่างกัน Dataclasses เป็นตัวเลือก standard library ที่ไม่มี dependencies Pydantic เพิ่มการตรวจสอบที่ runtime TypedDict ใส่ annotations ใน plain dicts โดยไม่สร้าง class ใหม่
ตัวอย่างโค้ด
ตัวอย่างเหล่านี้แสดงวิธีใช้ dataclasses ที่สร้างขึ้นใน Python วิธีสร้างจาก JavaScript แบบ programmatic และวิธีใช้ทางเลือกอย่าง Pydantic และ CLI tools
from dataclasses import dataclass
from typing import List, Optional
import json
@dataclass
class Address:
street: str
city: str
zip: str
@dataclass
class User:
id: int
name: str
email: str
active: bool
score: float
address: Address
tags: List[str]
metadata: Optional[str] = None
raw = '{"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"],"metadata":null}'
data = json.loads(raw)
# Reconstruct nested objects manually
addr = Address(**data["address"])
user = User(**{**data, "address": addr})
print(user.name) # -> Alice
print(user.address) # -> Address(street='123 Main St', city='Springfield', zip='12345')// Minimal JSON-to-Python-dataclass generator in JS
function jsonToPython(obj, name = "Root") {
const classes = [];
function infer(val, fieldName) {
if (val === null) return "Optional[str]";
if (typeof val === "string") return "str";
if (typeof val === "number") return Number.isInteger(val) ? "int" : "float";
if (typeof val === "boolean") return "bool";
if (Array.isArray(val)) {
const first = val.find(v => v !== null);
return first ? `List[${infer(first, fieldName + "Item")}]` : "List[Any]";
}
if (typeof val === "object") {
const clsName = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
build(val, clsName);
return clsName;
}
return "Any";
}
function build(obj, cls) {
const fields = Object.entries(obj).map(([k, v]) => ` ${k}: ${infer(v, k)}`);
classes.push(`@dataclass\nclass ${cls}:\n${fields.join("\n")}`);
}
build(obj, name);
return classes.join("\n\n");
}
const data = { id: 1, name: "Alice", scores: [98, 85] };
console.log(jsonToPython(data, "User"));
// @dataclass
// class User:
// id: int
// name: str
// scores: List[int]from pydantic import BaseModel
from typing import List, Optional
class Address(BaseModel):
street: str
city: str
zip: str
class User(BaseModel):
id: int
name: str
email: str
active: bool
score: float
address: Address
tags: List[str]
metadata: Optional[str] = None
# Pydantic parses and validates JSON in one step
raw = '{"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"],"metadata":null}'
user = User.model_validate_json(raw)
print(user.name) # -> Alice
print(user.model_dump_json()) # -> re-serializes to JSON# Install the generator
pip install datamodel-code-generator
# Generate dataclasses from a JSON file
datamodel-codegen --input data.json --output models.py --output-model-type dataclasses.dataclass
# Generate Pydantic models instead
datamodel-codegen --input data.json --output models.py
# From a JSON string via stdin
echo '{"id": 1, "name": "Alice", "tags": ["admin"]}' | \
datamodel-codegen --output-model-type dataclasses.dataclass
# Output:
# @dataclass
# class Model:
# id: int
# name: str
# tags: List[str]