Die Konvertierung von JSON in Python-Dataclasses ist eine der haufigsten Aufgaben in der modernen Python-Entwicklung. Wenn Ihre Anwendung eine JSON-Antwort von einer REST-API erhalt, benotigen Sie gut strukturierte Python-Dataclasses, Pydantic-Modelle oder TypedDicts. Dieser Leitfaden behandelt Typ-Mapping, JSON-Parsing-Strategien, Pydantic, attrs, TypedDict und Best Practices.
Testen Sie unseren kostenlosen Online JSON-zu-Python-Dataclass-Konverter.
Was ist JSON-zu-Python-Dataclass-Konvertierung?
JSON ist das dominierende Datenaustauschformat fur Web-APIs. Python profitiert enorm von expliziten Typdefinitionen uber Dataclasses, Pydantic-Modelle und TypedDicts. Die JSON-zu-Python-Konvertierung analysiert ein JSON-Dokument und erzeugt entsprechende Python-Klassen.
In einer typischen FastAPI-Anwendung empfangt ein Route-Handler den HTTP-Request-Body als JSON-String. Das Framework muss dieses JSON mit Pydantics BaseModel in Python-Objekte konvertieren. Ein JSON-zu-Python-Konverter automatisiert die Erstellung dieser Datenmodelle.
Die gleiche Konvertierung ist in Django REST Framework, in Datenpipelines und in CLI-Tools wesentlich. Der Prozess ist identisch: JSON-Struktur inspizieren, Feldtypen bestimmen, Verschachtelung und Arrays behandeln.
JSON zu Python: Typ-Mapping
Das Verstandnis der Zuordnung von JSON-Typen zu Python-Typen ist die Grundlage:
| JSON-Typ | Beispiel | Python-Typ(en) | Hinweise |
|---|---|---|---|
| string | "hello" | str | Immer str; datetime fur ISO-Daten |
| number (ganzzahlig) | 42 | int | Beliebige Prazision in Python |
| number (dezimal) | 3.14 | float, Decimal | Decimal fur Finanzdaten |
| boolean | true | bool | Direkte Zuordnung |
| null | null | None | Optional[T] oder T | None |
| array | [1,2] | list[T] | list[T] ab Python 3.9+ |
| object | {"k":"v"} | Verschachtelte Klasse | Stark typisierte Klassen bevorzugt |
Bei der Generierung von Python-Dataclasses aus JSON hangt die Wahl zwischen Optional[str] und str | None von der Python-Version ab. Fur Geldwerte immer Decimal verwenden.
Wie die JSON-zu-Python-Konvertierung funktioniert
Ein JSON-zu-Python-Dataclass-Konverter folgt einem systematischen Prozess:
- JSON-Struktur parsen: Parsing mit Pythons eingebautem
json-Modul. - Feldtypen ableiten: Python-Typ fur jedes Schlussel-Wert-Paar bestimmen.
- Klassennamen generieren: Konvertierung in PascalCase und snake_case.
- Verschachtelte Objekte behandeln: Jedes Objekt erzeugt eine separate Klasse.
- Arrays behandeln: Elementtyp-Analyse.
- Typ-Annotationen hinzufugen: PEP 484/604 Syntax.
- Quellcode ausgeben: Formatierter Python-Code.
Codebeispiele: JSON zu Python mit Pydantic, dataclasses, TypedDict und attrs
Pydantic v2: BaseModel, Field und Validatoren
Pydantic ist die am weitesten verbreitete JSON-zu-Python-Bibliothek. FastAPI verwendet sie standardmassig:
# === Sample JSON ===
# {
# "user_id": 1001,
# "user_name": "Alice",
# "email": "alice@example.com",
# "is_active": true,
# "balance": 1250.75,
# "tags": ["admin", "developer"],
# "address": {
# "street": "123 Main St",
# "city": "Springfield",
# "zip_code": "62704"
# }
# }
# === Pydantic v2 Models ===
from pydantic import BaseModel, Field, field_validator, ConfigDict
from typing import Optional
class Address(BaseModel):
street: str
city: str
zip_code: str = Field(alias="zipCode")
model_config = ConfigDict(populate_by_name=True)
class User(BaseModel):
user_id: int
user_name: str
email: str
is_active: bool = True
balance: float = 0.0
tags: list[str] = []
address: Optional[Address] = None
@field_validator("email")
@classmethod
def validate_email(cls, v: str) -> str:
if "@" not in v:
raise ValueError("Invalid email address")
return v.lower().strip()
model_config = ConfigDict(populate_by_name=True)
# === Parsing JSON string directly ===
json_string = '{"user_id": 1001, "user_name": "Alice", ...}'
user = User.model_validate_json(json_string)
# === Parsing from dict ===
data = {"user_id": 1001, "user_name": "Alice", "email": "alice@example.com"}
user = User.model_validate(data)
# === Serialization ===
print(user.model_dump()) # dict output
print(user.model_dump_json()) # JSON string output
# === List of models ===
from pydantic import TypeAdapter
users_adapter = TypeAdapter(list[User])
users = users_adapter.validate_json(json_array_string)dataclasses + json: @dataclass, dataclass_json, dacite
Pythons eingebautes dataclasses-Modul bietet eine leichtgewichtige Alternative:
from dataclasses import dataclass, field
from typing import Optional
import json
# === Standard dataclass ===
@dataclass
class Address:
street: str
city: str
zip_code: str
@dataclass
class User:
user_id: int
user_name: str
email: str
is_active: bool = True
balance: float = 0.0
tags: list[str] = field(default_factory=list)
address: Optional[Address] = None
def __post_init__(self):
# Convert nested dict to Address if needed
if isinstance(self.address, dict):
self.address = Address(**self.address)
# === Parse from JSON ===
raw = json.loads(json_string)
user = User(**raw)
# === Using dacite for nested structures ===
import dacite
data = json.loads(json_string)
user = dacite.from_dict(data_class=User, data=data)
# dacite handles nested dicts, Optional, Union automatically
# === Using dataclasses-json ===
from dataclasses_json import dataclass_json, LetterCase, config
@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass
class Product:
product_id: int
product_name: str
unit_price: float
in_stock: bool = True
# Direct JSON parsing
product = Product.from_json('{"productId": 42, "productName": "Keyboard", ...}')
# Direct JSON serialization
json_output = product.to_json()
# === Frozen (immutable) dataclass ===
@dataclass(frozen=True, slots=True)
class ImmutableConfig:
host: str
port: int
debug: bool = FalseTypedDict: Typ-Hinweise ohne Laufzeit-Overhead
Wenn Sie Python-JSON-Parsing mit Typsicherheit aber null Laufzeit-Overhead benotigen:
from typing import TypedDict, NotRequired
import json
# === TypedDict definitions ===
class Address(TypedDict):
street: str
city: str
zip_code: str
class User(TypedDict):
user_id: int
user_name: str
email: str
is_active: bool
balance: float
tags: list[str]
address: NotRequired[Address] # Python 3.11+
# === Parse JSON with type safety ===
raw: str = '{"user_id": 1001, "user_name": "Alice", ...}'
data: User = json.loads(raw) # type checker knows the shape
# Access with full IDE autocompletion
print(data["user_name"]) # str
print(data["balance"]) # float
print(data["tags"]) # list[str]
# === TypedDict with total=False for all-optional ===
class PartialUpdate(TypedDict, total=False):
user_name: str
email: str
is_active: bool
# === Combining Required and Optional fields ===
class BaseUser(TypedDict):
user_id: int # required
user_name: str # required
class FullUser(BaseUser, total=False):
email: str # optional
is_active: bool # optional
tags: list[str] # optional
# TypedDict has ZERO runtime overhead:
# no validation, no classes instantiated
# purely for static type checking with mypy/pyrightattrs: @define und cattrs fur strukturierte Daten
Die attrs-Bibliothek bietet mehr Funktionen als dataclasses, einschliesslich Validatoren und Konverter:
import attrs
from attrs import define, field, validators
import cattrs
import json
# === attrs with @define (modern API) ===
@define
class Address:
street: str
city: str
zip_code: str
@define
class User:
user_id: int
user_name: str
email: str = field(validator=validators.matches_re(r".+@.+\..+"))
is_active: bool = True
balance: float = 0.0
tags: list[str] = field(factory=list)
address: Address | None = None
# === cattrs for JSON structuring/unstructuring ===
converter = cattrs.Converter()
# Structure (dict -> attrs class)
raw = json.loads(json_string)
user = converter.structure(raw, User)
# Unstructure (attrs class -> dict)
data = converter.unstructure(user)
json_output = json.dumps(data)
# === Custom hooks for field name mapping ===
converter.register_structure_hook(
User,
cattrs.gen.make_dict_structure_fn(
User,
converter,
user_id=cattrs.gen.override(rename="userId"),
user_name=cattrs.gen.override(rename="userName"),
)
)
# Now parses camelCase JSON keys to snake_case fields
camel_data = {"userId": 1, "userName": "Alice", "email": "a@b.com"}
user = converter.structure(camel_data, User)
# === Frozen attrs class (immutable) ===
@define(frozen=True)
class Config:
host: str
port: int
debug: bool = FalseArbeiten mit verschachtelten JSON-Strukturen
Reale APIs liefern selten flaches JSON. Die meisten Antworten enthalten verschachtelte Objekte und polymorphe Typen:
Verschachtelte Modelle: Jede Verschachtelungsebene erzeugt eine separate Python-Klasse. Pydantic validiert rekursiv.
List[Model] und Optional-Felder: Ein Feld wie "items": [{"id": 1}] wird zu list[Item] in Python.
Union-Typen und diskriminierte Unions: Pydantics Discriminator bietet typsichere Deserialisierung.
# Discriminated union with Pydantic v2
from pydantic import BaseModel, Discriminator, Tag, TypeAdapter
from typing import Annotated, Literal, Union
class EmailNotification(BaseModel):
type: Literal["email"]
message: str
recipient: str
subject: str
class SmsNotification(BaseModel):
type: Literal["sms"]
message: str
phone_number: str
class PushNotification(BaseModel):
type: Literal["push"]
message: str
device_token: str
title: str
Notification = Annotated[
Union[
Annotated[EmailNotification, Tag("email")],
Annotated[SmsNotification, Tag("sms")],
Annotated[PushNotification, Tag("push")],
],
Discriminator("type"),
]
# Usage:
data = {"type": "email", "message": "Hello", "recipient": "a@b.com", "subject": "Hi"}
notif = TypeAdapter(Notification).validate_python(data)
isinstance(notif, EmailNotification) # True
# JSON input automatically resolves to the correct type
json_str = '{"type": "sms", "message": "Alert", "phone_number": "+1234567890"}'
sms = TypeAdapter(Notification).validate_json(json_str)
isinstance(sms, SmsNotification) # TrueFortgeschrittene Muster: Pydantic Settings, JSON Schema, Validatoren und berechnete Felder
Pydantic Settings ladt Konfiguration aus JSON-Dateien, Umgebungsvariablen und .env-Dateien:
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field
class AppSettings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
json_file="config.json",
)
app_name: str = "MyApp"
debug: bool = False
database_url: str = Field(alias="DATABASE_URL")
redis_url: str = "redis://localhost:6379"
max_connections: int = 100
# Loads from config.json, .env, and environment variables
# Priority: env vars > .env file > json file > defaults
settings = AppSettings()
print(settings.database_url)
print(settings.max_connections)JSON Schema-Generierung ist in Pydantic v2 eingebaut. Jedes BaseModel kann ein JSON Schema erzeugen:
from pydantic import BaseModel
import json
class Product(BaseModel):
id: int
name: str
price: float
tags: list[str] = []
# Generate JSON Schema
schema = Product.model_json_schema()
print(json.dumps(schema, indent=2))
# Output:
# {
# "title": "Product",
# "type": "object",
# "properties": {
# "id": {"title": "Id", "type": "integer"},
# "name": {"title": "Name", "type": "string"},
# "price": {"title": "Price", "type": "number"},
# "tags": {"title": "Tags", "type": "array",
# "items": {"type": "string"}, "default": []}
# },
# "required": ["id", "name", "price"]
# }
# Use schema for API docs, validation, or code generation
# FastAPI uses this automatically for OpenAPI documentationBenutzerdefinierte Validatoren und Serialisierungs-Aliase ermoglichen Datentransformation und Feldnamen-Kontrolle:
from pydantic import BaseModel, Field, field_validator, computed_field
from datetime import datetime
class User(BaseModel):
first_name: str = Field(alias="firstName")
last_name: str = Field(alias="lastName")
email: str
birth_date: datetime = Field(alias="birthDate")
@field_validator("email")
@classmethod
def validate_email(cls, v: str) -> str:
if "@" not in v:
raise ValueError("Invalid email address")
return v.lower().strip()
@computed_field
@property
def full_name(self) -> str:
return f"{self.first_name} {self.last_name}"
@computed_field
@property
def age(self) -> int:
today = datetime.now()
return today.year - self.birth_date.year
# Parse from JSON with camelCase keys
user = User.model_validate_json(
'{"firstName":"Alice","lastName":"Smith",'
'"email":"ALICE@example.com","birthDate":"1990-05-15T00:00:00"}'
)
print(user.full_name) # "Alice Smith"
print(user.email) # "alice@example.com"
print(user.age) # computed from birth_date
# Computed fields appear in serialized output
print(user.model_dump())
# {"first_name": "Alice", "last_name": "Smith",
# "email": "alice@example.com", "birth_date": ...,
# "full_name": "Alice Smith", "age": 35}Best Practices fur JSON-zu-Python-Konvertierung
Befolgen Sie diese Best Practices fur robuste Anwendungen:
Pydantic fur API-Code: Validierung, Serialisierung und JSON Schema-Generierung inklusive.
Dataclasses fur interne Strukturen: Leichtgewichtige Container ohne Validierungs-Overhead.
Optionale Felder explizit behandeln: Optional[T] oder T | None mit Standard None.
Aliase fur Namenskonventionen: Field(alias="camelCase") in Pydantic.
Fruh validieren, schnell fehlschlagen: @field_validator in Pydantic hinzufugen.
Strikten Modus verwenden: ConfigDict(strict=True) verhindert implizite Typkonvertierung.
Typen aus JSON Schema generieren: datamodel-code-generator fur automatische Modellgenerierung.
Verwandte Tools: JSON zu Java, JSON zu TypeScript, JSON zu Dart.
JSON to JavaJSON to TypeScriptJSON to Dart
Haufig gestellte Fragen
Pydantic oder dataclasses: Was soll ich verwenden?
Verwenden Sie Pydantic fur Validierung, JSON Schema und FastAPI-Integration. Verwenden Sie dataclasses fur leichtgewichtige Container. Pydantic bietet auch einen Dataclass-Dekorator, der Validierung zu Standard-Dataclasses hinzufugt.
Wie konvertiere ich ein Python-Dict in eine Dataclass?
Pydantic: User.model_validate({"name": "Alice"}). Dataclasses: dacite.from_dict(data_class=User, data=my_dict). Einfach: User(**my_dict).
Wie behandle ich verschachteltes JSON mit optionalen Feldern?
Pydantic behandelt verschachtelte Modelle automatisch. Verwenden Sie Optional[NestedModel] = None. Pydantic validiert rekursiv. Fur dataclasses verwenden Sie dacite oder dataclasses-json.
Die Konvertierung von JSON zu Python-Dataclasses ist eine grundlegende Fahigkeit. Nutzen Sie unser kostenloses Tool fur sofortige Generierung und diesen Leitfaden fur Best Practices.
Konvertieren Sie JSON sofort in Python-Dataclasses mit unserem kostenlosen Tool.