JSON zu Python: dataclass, Pydantic & TypedDict (Guide 2026)
Fügen Sie Ihr JSON in den JSON-zu-Python-Konverter ein und kopieren Sie die Klassen, die er erzeugt. Das ist der schnelle Weg, um JSON in Python zu überführen: nichts zu installieren, nichts wird hochgeladen, alles läuft im Browser. Für ein einmaliges Modell oder einen kurzen Blick auf eine unbekannte API-Antwort sind Sie in Sekunden fertig.
Das schwierigere Problem kann Ihnen ein Konverter nicht abnehmen. Er leitet korrekte Typen ab, aber die wichtigste Entscheidung trifft er nicht: welche der drei Ausgaben Sie tatsächlich brauchen. Ein dataclass, ein Pydantic-v2-BaseModel und ein TypedDict können exakt dasselbe JSON beschreiben, unterscheiden sich aber in der Stärke der Typsicherheit, im Laufzeitverhalten und darin, wie Sie Daten hineinladen. Wählen Sie falsch, schleppen Sie entweder Pydantics Abhängigkeit ohne Nutzen mit, oder Sie gehen davon aus, dass ein dataclass Ihre Eingabe prüft, obwohl er das gar nicht tut.
Dieser Guide behandelt die Entscheidungsmatrix für alle drei, wie der Konverter Typen ableitet, den Umgang mit camelCase in jedem Modus, wie Sie JSON mit der erzeugten Klasse parsen (samt der Falle mit verschachtelten Objekten, in die viele tappen), Pydantic v2 gegenüber v1 und die Randfälle, die Sie kennen sollten, bevor Sie der Ausgabe vertrauen.
So wandeln Sie JSON in Python um
Die Umwandlung von JSON in Python erfolgt in drei Schritten:
- Fügen Sie Ihr JSON ein. Werfen Sie ein Objekt, ein Array oder eine rohe API-Antwort in das Eingabefeld. Die Umwandlung läuft sofort und vollständig clientseitig.
- Wählen Sie dataclass, Pydantic oder TypedDict. Wechseln Sie den Stil über den Output-Umschalter und benennen Sie das voreingestellte
Rootin etwas Aussagekräftiges um, etwaUseroderApiResponse. - Kopieren oder herunterladen. Holen Sie sich das erzeugte Python mit einem Klick und legen Sie
models.pydirekt in Ihr Projekt.
Das ist der komplette transaktionale Ablauf. Ist Ihre Eingabe minifiziert oder sind Sie nicht sicher, ob sie gültig ist, schicken Sie sie zuerst durch einen JSON-Formatierer, damit der Konverter sauberes, wohlgeformtes JSON zu lesen bekommt. Der Rest dieses Guides erklärt die Ausgabe, damit Sie die Fälle selbst korrigieren können, die ein Werkzeug nicht von allein ableiten kann.
Wie sich JSON-Typen auf Python abbilden
Jeder JSON-Wert hat ein Python-Gegenstück, und die Abbildung ist unkompliziert:
| JSON-Wert | Python-Typ |
|---|---|
"text" | str |
42 | int (beliebige Genauigkeit, kein Überlauf) |
3.14, 2e3 | float |
true / false | bool |
null | Optional[T] / Optional[Any] |
[1, 2, 3] | List[T] |
{ ... } | eine benannte Klasse |
Nehmen Sie eine typische REST-Nutzlast:
{ "id": 101, "name": "Ada Lovelace", "email": "ada@example.com", "active": true, "roles": ["admin", "user"] }
Im dataclass-Modus erzeugt der Konverter eine einsatzbereite Klasse:
from dataclasses import dataclass
from typing import List
@dataclass
class Root:
id: int
name: str
email: str
active: bool
roles: List[str]
Eine Feinheit hebt Python ab. Sein int hat beliebige Genauigkeit, sodass ein Discord-Snowflake oder jede ID jenseits von 2^53 ein schlichter int bleibt, ganz ohne Verlust. JavaScript würde beim selben Wert an Genauigkeit verlieren, und Rust zwänge Sie zur Wahl zwischen i64, u64 und f64. Nur ein Token mit Dezimalpunkt oder Exponent wird als float abgeleitet. Ein Feld, das immer nur null ist, lässt sich aus dem Beispiel allein nicht typisieren und fällt deshalb auf Optional[Any] zurück; fügen Sie eine repräsentative Nutzlast mit gefülltem Wert ein, um etwas Schärferes als Any zu erhalten.
dataclass vs. Pydantic v2 vs. TypedDict – welche sollten Sie nehmen?
Das ist die Entscheidung, die der Konverter an Sie zurückgibt, und der Kern dieses Guides. Kurz gefasst: Greifen Sie zu einem dataclass, wenn Sie einen abhängigkeitsfreien internen Datencontainer wollen, zu Pydantic v2, wenn Sie nicht vertrauenswürdige Eingaben parsen oder validieren, und zu TypedDict, wenn Sie nur statische Typhinweise über bereits vorhandene dicts brauchen.
| Dimension | dataclass | Pydantic v2 | TypedDict |
|---|---|---|---|
| Abhängigkeit | Standardbibliothek | pip install pydantic | Standardbibliothek (typing) |
| Laufzeit-Validierung | Nein | Ja – validiert und konvertiert | Nein – nur Hinweise |
| Laufzeitkosten | Gering (echtes Objekt) | Etwas (Validierung) | Null (es ist ein dict) |
| Automatisches Parsen verschachtelter Objekte | Nein, manuell | Ja, model_validate rekursiv | Nein, es ist ein dict |
| camelCase-Aliase | behält den Originalschlüssel | Field(alias=...) | funktionale Syntax |
| Am besten für | interne Strukturen | API-Antworten, Webhooks, Konfiguration | Typisierung von Alt-dict-Code |
Für eine kleine Struktur wie {"id": 101, "name": "Ada Lovelace", "active": true} sehen die drei Ziele fast gleich aus. Ein JSON-zu-Python-dataclass gibt Ihnen ein Objekt aus der Standardbibliothek:
from dataclasses import dataclass
@dataclass
class Root:
id: int
name: str
active: bool
Die JSON-zu-Pydantic-Variante tauscht BaseModel ein, das ähnlich aussieht, sich aber zur Laufzeit bezahlt macht:
from pydantic import BaseModel
class Root(BaseModel):
id: int
name: str
active: bool
Und ein Python-TypedDict aus JSON beschreibt die Struktur eines einfachen dict, ohne etwas Neues zu allozieren:
from typing import TypedDict
class Root(TypedDict):
id: int
name: str
active: bool
Dieselben Felder, drei sehr unterschiedliche Verträge. Der Vorteil, alle drei aus einem Beispiel zu erzeugen: Sie können im Werkzeug zwischen ihnen umschalten und den Modus an die Aufgabe anpassen: Pydantic, wenn Sie Daten parsen, die Sie nicht kontrollieren, ein dataclass, wenn die Daten intern sind, und TypedDict, wenn mypy einfach nur ein dict verstehen soll, das Sie ohnehin schon herumreichen.
Wie der Konverter Klassen ableitet
Drei Regeln decken fast alles ab, was Sie ihm geben: eine Klasse pro Objektstruktur, schlüsselweises Zusammenführen bei Arrays und sorgfältiger Umgang mit fehlenden Werten.
Strukturelle Ableitung: eine benannte Klasse pro Objekt
Jede eigenständige Objektstruktur wird zu ihrer eigenen benannten Klasse. Verschachtelte Objekte werden nicht eingebettet, sondern in eigene, referenzierte Definitionen ausgelagert:
{ "repo": "pydantic", "owner": { "login": "samuelcolvin", "id": 100 } }
from dataclasses import dataclass
@dataclass
class Owner:
login: str
id: int
@dataclass
class Root:
repo: str
owner: Owner
Das verschachtelte owner wird zu einer eigenen Owner-Klasse, die per Feld referenziert wird. Beachten Sie die Reihenfolge: Die Kindklasse wird vor dem Elternteil ausgegeben, das sie verwendet, sodass das Modul ohne from __future__ import annotations läuft. Identische Strukturen werden zudem dedupliziert, sodass sich zwei Felder mit derselben Struktur eine Klasse teilen, statt Kopien zu erzeugen.
Array-Zusammenführung und Optional-Felder
Wenn Sie ein Array von Objekten übergeben, führt der Konverter sie schlüsselweise zu einem einzigen Elementtyp zusammen. Ein Schlüssel, der in manchen Elementen vorhanden, in anderen aber nicht ist, wird zu Optional:
{ "users": [{ "id": 1, "nick": "x" }, { "id": 2 }] }
from typing import List, Optional, TypedDict
class User(TypedDict):
id: int
nick: Optional[str]
class Root(TypedDict):
users: List[User]
id erscheint in jedem Element und bleibt daher erforderlich. nick fehlt beim zweiten Benutzer und wird deshalb zu Optional[str]. Genau darum ist ein einzelnes Objekt ein schwaches Beispiel: Das Werkzeug kann ein Feld nur dann als Optional markieren, wenn es den Schlüssel irgendwo tatsächlich fehlen sieht. Geben Sie ein repräsentatives Array ein, und die Ableitung spiegelt die reale Struktur wider.
Optional, None und leere Arrays
Einige Werte tragen von sich aus keinen Typ, und der Konverter geht offen damit um. Ein Schlüssel, der in manchen Array-Elementen fehlt, wird zu Optional[T]. Ein Feld, das immer nur null ist, wird zu Optional[Any], weil JSON null allein nichts über den beabsichtigten Typ verrät. Ein leeres Array oder eines mit gemischten Elementtypen fällt auf List[Any] zurück. Nichts davon ist ein Fehler; das Werkzeug verzichtet hier bewusst aufs Raten. Ersetzen Sie jedes Any durch einen konkreten Typ, sobald Sie ein Beispiel dafür haben, und denken Sie daran: Pythons int mit beliebiger Genauigkeit sorgt dafür, dass eine große ID Sie nie in einen breiteren Zahlentyp zwingt, wie es in Rust oder JavaScript der Fall wäre.
Umgang mit camelCase-Schlüsseln in jedem Modus
JSON-Schlüssel sind oft camelCase, während idiomatische Python-Felder snake_case sind. Hier gibt es keine einzig richtige Antwort, also löst jeder Modus das anders. Den Unterschied sollten Sie verstehen, bevor Sie die Ausgabe kopieren.
dataclass. Ein dataclass hat keinen eingebauten Alias-Mechanismus. Damit Root(**data) weiterhin funktioniert, behält der Konverter den Originalschlüssel als Feldnamen bei, sofern es ein gültiger Python-Bezeichner ist. publicRepos bleibt also publicRepos. Es zwangsweise nach snake_case zu wandeln, würde **data mit einem TypeError brechen.
Pydantic v2. Hier bekommen Sie das idiomatische Ergebnis. Felder werden in snake_case umbenannt, mit einem Field(alias=...), das auf den exakten JSON-Schlüssel zurückverweist, plus model_config = ConfigDict(populate_by_name=True), sodass Sie das Modell über den Feldnamen oder den Alias aufbauen können:
from pydantic import BaseModel, ConfigDict, Field
class Root(BaseModel):
model_config = ConfigDict(populate_by_name=True)
login: str
public_repos: int = Field(alias="publicRepos")
created_at: str = Field(alias="createdAt")
Genau das lässt Root.model_validate(api_json) echte camelCase-Nutzlasten hin und zurück verarbeiten, während sich Ihr Code natürlich liest.
TypedDict. Schlichte Bezeichnerschlüssel werden direkt verwendet. Sobald ein Schlüssel auftaucht, der kein Bezeichner ist, wechselt der Konverter zur funktionalen Syntax TypedDict('User', {...}), um den exakten Schlüssel zu bewahren; mehr dazu im nächsten Abschnitt.
Python-Schlüsselwörter und Nicht-Bezeichner-Schlüssel
JSON-Schlüssel sind nur Zeichenketten, also hindert nichts eine API daran, class, from oder first-name zu senden. Jeder davon wäre als bloßes Python-Attribut ein Syntaxfehler, deshalb bereinigt der Konverter sie.
Ein Schlüssel, der ein Python-Schlüsselwort ist, erhält einen angehängten Unterstrich: class wird zu class_, from wird zu from_. Im Pydantic-Modus behält er zudem ein Field(alias=...), damit das Modell weiterhin den ursprünglichen Wire-Schlüssel liest:
from pydantic import BaseModel, ConfigDict, Field
class Root(BaseModel):
model_config = ConfigDict(populate_by_name=True)
class_: str = Field(alias="class")
from_: str = Field(alias="from")
Schlüssel mit Bindestrichen, Leerzeichen oder einer führenden Ziffer werden im dataclass- und im Pydantic-Modus zu gültigen Bezeichnern bereinigt. TypedDict ist der einzige Modus, der den wörtlichen Schlüssel behalten kann, indem er die funktionale Form verwendet, sodass "first-name" unangetastet erhalten bleibt:
from typing import TypedDict
Root = TypedDict("Root", {"first-name": str, "2fa": bool})
Das Ergebnis läuft immer, und im TypedDict-Modus bleibt der Schlüssel Byte für Byte das, was die API gesendet hat.
JSON mit der erzeugten Klasse parsen
Die Klasse zu erzeugen ist die halbe Arbeit. Beim Laden von JSON in sie gehen die drei Modi deutlich auseinander. Hier läuft eine verbreitete Annahme schief.
dataclass. Bei einem flachen Objekt funktioniert json.loads plus Root(**data) direkt:
import json
from dataclasses import dataclass
from typing import List
@dataclass
class Root:
id: int
name: str
roles: List[str]
data = json.loads('{"id": 101, "name": "Ada Lovelace", "roles": ["admin"]}')
root = Root(**data)
print(root.name, root.roles)
Aber ein dataclass geht nicht in die Tiefe. Hat das JSON verschachtelte Objekte, füllt Root(**data) die oberste Ebene und lässt jedes Kind als schlichtes dict zurück, nicht als die Owner-Klasse, die Sie erzeugt haben. Um einen ganzen Baum zu parsen, bauen Sie die Kinder selbst, nutzen eine Bibliothek wie dacite oder pydantic.dataclasses oder stellen das Werkzeug auf den Pydantic-Modus um. Das ist der Fallstrick, den die meisten Konverter nie erwähnen.
Pydantic v2. Ein einziger Aufruf parst und validiert den gesamten Baum:
import json
from pydantic import BaseModel
class Root(BaseModel):
id: int
name: str
root = Root.model_validate(json.loads('{"id": 101, "name": "Ada Lovelace"}'))
print(root.name)
Eine Typabweichung löst einen klaren ValidationError aus, statt still durchzugehen. Das ist der Lohn für die Abhängigkeit: Das Modell ist ein Laufzeit-Validierer, sodass ein model_validate-Aufruf, der zurückkehrt, eine Garantie ist, dass die Daten passten, nicht nur die Vermutung eines Typprüfers, dass sie es taten.
TypedDict. Zur Laufzeit ist ein TypedDict ein gewöhnliches dict. Die Annotation data: Root = json.loads(text) dient rein dem statischen Prüfer; beim Ausführen des Codes wird nichts validiert. Brauchen Sie echte Durchsetzung, lassen Sie mypy in der CI laufen oder wechseln zu Pydantic. Einen Modus zu wählen heißt zu wählen, wie viel Laufzeitgarantie Sie möchten, und wenn ein Vertrag über Typen hinausgehen muss, zeigt der Guide zur JSON-Schema-Validierung, wie sich Struktur durchgängig erzwingen lässt.
Pydantic v2 vs. v1 – was sich geändert hat
Der Konverter gibt v2-Syntax aus. Viele Codebasen laufen noch mit v1, und v2-Ausgabe in ein v1-Projekt einzufügen scheitert an umbenannten Methoden, nicht an der Logik. Hier die Zuordnung:
| Aufgabe | Pydantic v2 (Werkzeug-Ausgabe) | Pydantic v1 |
|---|---|---|
| Ein dict parsen | model_validate(data) | parse_obj(data) |
| Rohes JSON parsen | model_validate_json(text) | parse_raw(text) |
| Das Modell konfigurieren | model_config = ConfigDict(...) | inneres class Config |
| In ein dict serialisieren | model_dump() | dict() |
| In JSON serialisieren | model_dump_json() | json() |
Auch das Alias-Verhalten wurde strenger: In v2 brauchen Sie populate_by_name=True neben Field(alias=...), um ein Modell wahlweise über den Feldnamen oder den Alias zu erstellen, weshalb das Werkzeug es einbindet. Steigen Sie auf v2 um, wenn Sie können, denn es ist schneller und das Ziel der aktuellen Entwicklung; andernfalls schreiben Sie model_validate wieder zu parse_obj und ConfigDict wieder zu einem inneren Config um.
json-to-python vs. quicktype vs. datamodel-code-generator vs. manuell
Es gibt keinen einzig besten Weg, eine Python-Klasse aus JSON zu erzeugen. Es hängt davon ab, wo das JSON liegt und womit Sie starten.
| Ansatz | Am besten für | Hinweis |
|---|---|---|
| Online-Konverter (dieses Werkzeug, jsonlint, codeshack) | einmalige Umwandlungen, sensible Nutzlasten, keine Installation | leitet aus einem Beispiel ab, vollständig clientseitig |
| quicktype | Ausgabe für mehrere Sprachen, Codegen in der Pipeline | ebenfalls beispielgesteuert; die Python-Unterstützung ist bei Aliassen und Moduswahl dünner |
| datamodel-code-generator | Pydantic aus einem JSON-Schema oder OpenAPI erzeugen | Eingabe ist ein Schema, kein Beispiel – verbindlicher, wenn Sie eines haben |
| Klassen von Hand schreiben | winzige Nutzlasten, die Syntax lernen | volle Kontrolle, aber mühsam und leicht driftend |
Der Unterschied, den man verinnerlichen sollte: Ein Online-Konverter und quicktype leiten Typen beide aus einem Beispiel von JSON ab, während datamodel-code-generator ein JSON-Schema oder eine OpenAPI-Spezifikation als Quelle der Wahrheit liest. Nutzen Sie die beispielbasierten Werkzeuge zum Erkunden und für Einzelfälle; greifen Sie zum schemagesteuerten, wenn bereits ein Vertrag existiert. Ist Ihre Codebasis TypeScript statt Python, gilt derselbe beispielbasierte Ansatz mit dem JSON-zu-TypeScript-Konverter, und der Guide zu JSON-zu-TypeScript-Interfaces behandelt diese Seite ausführlich. Für den Blickwinkel der Laufzeit-Validierung in einer streng typisierten, kompilierten Sprache bietet der Guide zu JSON-zu-Rust-Structs einen nützlichen Kontrast: serde ist Rusts Pydantic.
Häufige Fallstricke beim Erzeugen von Python aus JSON
Erzeugte Klassen sind ein Ausgangspunkt. Achten Sie auf Folgendes, bevor Sie sich mit Live-Daten auf die Ausgabe verlassen.
- Ein einzelnes Beispiel offenbart selten jede Struktur.
Optionallässt sich nur aus Array-Elementen ableiten, die sich tatsächlich unterscheiden. Fügen Sie ein repräsentatives Array ein, damit die Optionalität stimmt und nicht aus einem glücklichen Objekt geraten ist. - Ein dataclass validiert nicht.
Root(**data)weist nur Felder zu; es prüft keine Typen und geht in nichts hinein. Brauchen Sie Durchsetzung, nehmen Sie Pydantic. - Verschachteltes JSON bricht
Root(**data). Nur die oberste Ebene wird gefüllt; Kinder bleiben dicts. Wechseln Sie zu Pydanticsmodel_validateoder nutzen Sie dacite. - Ein immer-
null-Feld wird zuOptional[Any]. Behandeln Sie es als Platzhalter, nicht als normales Optional, und geben Sie ihm einen echten Typ, sobald Sie einen kennen. - v2-Ausgabe in einem v1-Projekt.
model_validateist dann undefiniert. Steigen Sie auf v2 um oder schreiben Sie es zuparse_objum. - Ein als
strbelassenes Datum kann nicht rechnen. Stellen Sie das Feld aufdatetimeum, oder verwenden Sie in Pydantic eindatetime-Feld, damit es ISO 8601 für Sie parst.
Häufig gestellte Fragen
Sollte ich für JSON ein dataclass, Pydantic oder TypedDict verwenden?
Verwenden Sie ein dataclass für einen abhängigkeitsfreien internen Datencontainer. Verwenden Sie Pydantic v2, wenn Sie nicht vertrauenswürdige Eingaben parsen oder validieren, denn es erzwingt Typen zur Laufzeit. Verwenden Sie TypedDict, um einem bereits vorhandenen dict statische Hinweise hinzuzufügen, ohne Laufzeitkosten. Kommen die Daten von außerhalb Ihrer Kontrolle, greifen Sie standardmäßig zu Pydantic.
Validiert Pydantic JSON zur Laufzeit?
Ja. Root.model_validate(data) validiert und konvertiert Typen während der Ausführung und löst bei fehlerhafter Eingabe einen ValidationError aus. Ein dataclass tut weder das eine noch das andere; Root(**data) weist nur Felder zu. Ein TypedDict tut ebenfalls beides nicht; es ist ein Hinweis für statische Prüfer wie mypy und verhält sich zur Laufzeit wie ein schlichtes dict.
Wie typisiere ich ein Feld, das JSON manchmal weglässt?
Typisieren Sie es als Optional[T]. Erscheint ein Schlüssel nur in einigen Array-Elementen, markiert der Konverter ihn automatisch als Optional. Geben Sie dem Feld in Pydantic einen Standardwert wie = None, damit ein fehlender Schlüssel keinen Validierungsfehler auslöst. Ein dataclass-Feld lässt sich auf dieselbe Weise mit field(default=None) vorbelegen.
Warum konnte mein dataclass verschachteltes JSON nicht parsen?
Weil Root(**data) nicht in die Tiefe geht. Es füllt die Felder der obersten Ebene und lässt verschachtelte Objekte als schlichte dicts zurück, statt als die Kindklassen, die Sie erzeugt haben. Um den ganzen Baum in einem Aufruf zu parsen, wechseln Sie zu Pydantics model_validate oder ergänzen Rekursion mit dacite oder pydantic.dataclasses.
Welchen Python-Typ erhält eine große JSON-Ganzzahl?
int. Python-Ganzzahlen haben beliebige Genauigkeit, sodass ein Snowflake oder eine Discord-ID jenseits von 2^53 ein schlichter int bleibt, ganz ohne Verlust. Sie stoßen nie auf den Genauigkeitsverlust von JavaScript, und Sie müssen sich nie zwischen i64 und u64 entscheiden, wie Rust es Ihnen aufzwingt.
Wie werden camelCase-JSON-Schlüssel in jedem Modus behandelt?
Ein dataclass behält den Originalschlüssel, damit Root(**data) weiterhin funktioniert. Pydantic benennt Felder in snake_case um, mit Field(alias="camelKey") plus populate_by_name=True, sodass echte API-Daten hin und zurück verarbeitet werden. TypedDict nutzt die funktionale Syntax TypedDict('Name', {...}), um jeden Schlüssel zu bewahren, der kein gültiger Bezeichner ist.
Wie gehe ich mit einem JSON-Schlüssel um, der ein Python-Schlüsselwort wie class ist?
Der Konverter hängt einen Unterstrich an und macht aus class ein class_, damit der Code gültig ist. Im Pydantic-Modus fügt er zudem Field(alias="class") hinzu, das das Feld auf den ursprünglichen Wire-Schlüssel zurückverweist, sodass der Name zulässig ist und das Modell weiterhin die echte Nutzlast liest.
Bleibt mein JSON bei einem Online-JSON-zu-Python-Konverter privat?
Ja. Die Umwandlung läuft zu 100 % in Ihrem Browser mit JavaScript. Ihr JSON (einschließlich Tokens, IDs und Kundendaten) verlässt die Seite nie und wird nie an einen Server gesendet. Es funktioniert sogar offline, sobald die Seite geladen ist. Wenn Sie so weit sind, probieren Sie den JSON-zu-Python-Konverter mit Ihrer eigenen Nutzlast aus.