Python JSON
Lerne, wie du Pythons eingebautes json-Modul zum Kodieren, Dekodieren, Lesen und Schreiben von JSON-Daten verwendest, mit Beispielen und Fehlerbehandlung.
Pythons eingebautes json-Modul ermöglicht die Konvertierung zwischen Python-Objekten und JSON-Text in den meisten Fällen mit nur zwei Funktionen. Dieses Kapitel behandelt alles, was du brauchst: Datentypzuordnung, dumps/loads für Strings, dump/load für Dateien, Pretty-Printing, Fehlerbehandlung und benutzerdefinierte Serialisierung.
Was ist JSON?
JSON (JavaScript Object Notation) ist ein leichtgewichtiges, textbasiertes Datenaustauschformat. Es ist für Menschen lesbar, sprachunabhängig und das Standardformat für die meisten Web-APIs.
Ein JSON-Dokument besteht aus zwei Strukturen:
- Objekte — ungeordnete Sammlungen von Schlüssel/Wert-Paaren, eingeschlossen in
{}. Schlüssel sind immer Strings in doppelten Anführungszeichen. - Arrays — geordnete Wertefolgen, eingeschlossen in
[].
Beispiel für ein JSON-Dokument:
{
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"],
"active": true,
"score": null
}Python–JSON-Typzuordnung
Beim Kodieren oder Dekodieren von JSON konvertiert Pythons json-Modul Typen gemäß dieser Tabelle:
| Python-Typ | JSON-Typ | Python-Typ (nach Dekodierung) |
|---|---|---|
dict | object {} | dict |
list, tuple | array [] | list |
str | string "" | str |
int, float | number | int oder float |
True / False | true / false | bool |
None | null | None |
Beachte, dass Tupel zu JSON-Arrays werden und nach der Dekodierung als Python-Listen zurückkommen.
Python-Objekte in JSON-Strings kodieren
json.dumps() (dump-string) serialisiert ein Python-Objekt in einen JSON-formatierten String.
Grundlegende Kodierung
Ausgabe:
{"name": "John Doe", "age": 30, "city": "New York", "hobbies": ["reading", "traveling", "photography"]}Pretty-Printing mit indent und sort_keys
Standardmäßig erzeugt json.dumps() einen kompakten einzeiligen String. Übergib indent, um eine für Menschen lesbare Ausgabe zu erzeugen, und sort_keys=True, um Dictionary-Schlüssel alphabetisch zu sortieren:
import json
person = {
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"]
}
print(json.dumps(person, indent=2, sort_keys=True))Ausgabe:
{
"age": 30,
"city": "New York",
"hobbies": [
"reading",
"traveling",
"photography"
],
"name": "John Doe"
}Verwende indent=2 oder indent=4 beim Schreiben von Konfigurationsdateien oder beim Debuggen von API-Antworten — das macht verschachtelte Strukturen leicht lesbar.
JSON-Strings in Python-Objekte dekodieren
json.loads() (load-string) parst einen JSON-String und gibt das entsprechende Python-Objekt zurück.
Grundlegende Dekodierung
Ausgabe:
{'name': 'John Doe', 'age': 30, 'city': 'New York', 'hobbies': ['reading', 'traveling', 'photography']}
<class 'dict'>
John DoeDer dekodierte Wert ist ein reguläres Python-Dictionary, du kannst also auf seine Schlüssel mit [] oder .get() zugreifen, es mit for iterieren und so weiter.
Fehlerhaftes JSON behandeln
Wenn die Eingabe kein gültiges JSON ist, wirft json.loads() einen json.JSONDecodeError. Fange ihn immer ab, wenn du mit Daten aus externen Quellen arbeitest:
import json
raw = '{"name": "Alice", "age":}' # invalid — missing value
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
print(f"Invalid JSON: {e}")Ausgabe:
Invalid JSON: Expecting value: line 1 column 24 (char 23)Weitere Informationen zur Ausnahmebehandlung findest du im Kapitel Python try/except.
Mit verschachteltem JSON arbeiten
JSON-Objekte können andere Objekte und Arrays in beliebiger Tiefe enthalten. Greife auf verschachtelte Werte mit verketteter []-Notation zu:
Ausgabe:
John
travelingBei tief verschachtelten Strukturen empfiehlt es sich, .get() mit einem Standardwert zu verwenden, um KeyError bei fehlenden Schlüsseln zu vermeiden:
city = person.get("address", {}).get("city", "unknown")Das Kapitel verschachtelte Dictionaries behandelt Muster für die Arbeit mit tief verschachtelten Python-Dicts.
JSON-Dateien lesen und schreiben
json.dump() schreibt in ein Dateiobjekt, und json.load() liest aus einem. Diese sind die Datei-Pendants von dumps/loads.
JSON in eine Datei schreiben
import json
data = {"name": "Alice", "scores": [95, 87, 92]}
with open("data.json", "w") as f:
json.dump(data, f, indent=2)Dadurch wird data.json mit pretty-gedrucktem Inhalt erstellt. Die Verwendung von with open(...) stellt sicher, dass die Datei automatisch geschlossen wird — weitere Details findest du unter Python-Dateiverarbeitung.
JSON aus einer Datei lesen
import json
with open("data.json") as f:
data = json.load(f)
print(data)
print(data["scores"])Ausgabe (unter der Annahme der oben geschriebenen Datei):
{'name': 'Alice', 'scores': [95, 87, 92]}
[95, 87, 92]Vollständiges Round-Trip-Beispiel
import json
# Write
config = {"host": "localhost", "port": 5432, "debug": False}
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
# Read back
with open("config.json") as f:
loaded = json.load(f)
print(loaded["port"]) # 5432
print(type(loaded["port"])) # <class 'int'>JSON von einer Web-API abrufen
In den meisten Projekten wirst du JSON dekodieren, das aus einer HTTP-Antwort stammt. Die beliebte requests-Bibliothek macht dies unkompliziert:
import requests
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
response.raise_for_status() # raises an error for 4xx/5xx responses
data = response.json() # equivalent to json.loads(response.text)
print(data["title"])
print(data["completed"])response.json() ruft intern json.loads() auf. Rufe immer raise_for_status() vor dem Parsen auf, damit eine fehlgeschlagene Anfrage nicht still einen Fehlerkörper zurückgibt.
Benutzerdefinierte Serialisierung mit default
Das json-Modul kann standardmäßig keine beliebigen Python-Objekte (wie datetime.date) kodieren. Übergib ein aufrufbares default oder eine benutzerdefinierte JSONEncoder-Unterklasse, um sie zu behandeln:
import json
import datetime
class DateEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.date):
return obj.isoformat()
return super().default(obj)
event = {"name": "Conference", "date": datetime.date(2024, 1, 15)}
print(json.dumps(event, cls=DateEncoder))Ausgabe:
{"name": "Conference", "date": "2024-01-15"}Das date-Objekt wird vor der Serialisierung in seinen ISO-8601-String konvertiert.
Benutzerdefinierte Deserialisierung mit object_hook
object_hook wird für jedes JSON-Objekt (Dict) beim Dekodieren aufgerufen. Du kannst es verwenden, um Daten im laufenden Betrieb zu transformieren — zum Beispiel String-Werte in die richtigen Python-Typen umzuwandeln:
import json
def as_record(d):
"""Convert age field from string to int if present."""
if "age" in d:
d["age"] = int(d["age"])
return d
raw = '{"name": "Bob", "age": "25"}'
person = json.loads(raw, object_hook=as_record)
print(person)
print(type(person["age"])) # <class 'int'>Ausgabe:
{'name': 'Bob', 'age': 25}
<class 'int'>Kurzreferenz
| Funktion | Richtung | Quelle/Ziel |
|---|---|---|
json.dumps(obj) | Python → JSON | gibt einen str zurück |
json.loads(s) | JSON → Python | liest aus einem str |
json.dump(obj, f) | Python → JSON | schreibt in eine Datei |
json.load(f) | JSON → Python | liest aus einer Datei |
Wichtige optionale Parameter:
indent=2— Pretty-Print mit 2-Leerzeichen-Einrückungsort_keys=True— Dictionary-Schlüssel alphabetisch sortierencls=MyEncoder— eine benutzerdefinierteJSONEncoder-Unterklasse verwendenobject_hook=fn— jedes dekodierte object-Dict transformieren