JSON Formatter Python — json.dumps() Guide

·Backend Developer·Geprüft vonDmitri Volkov·Veröffentlicht

Nutze das kostenlose JSON Formatter & Beautifier direkt im Browser – keine Installation erforderlich.

JSON Formatter & Beautifier online testen →

Wenn ich einen Python-API-Client debugge, greife ich als erstes zu python json pretty print — ein einziger Aufruf von json.dumps(data, indent=4) und ein unlesbarer einzeiliger Blob wird sofort navigierbar. Pythons eingebautes json-Modul erledigt das vollständig in der Standardbibliothek — kein Drittanbieter-Install erforderlich. Für ein schnelles Einmalergebnis ohne Code ist der JSON Formatter von ToolDeck der direktere Weg. Dieser Leitfaden deckt jede praktische Methode ab: json.dumps() mit allen Parametern, pprint, orjson für hochperformante Formatierung, das json.tool-CLI, und reale Szenarien wie das Formatieren von API-Antworten und Lesen von der Festplatte — alles mit Python-3.8+-kompatiblem Code. Außerdem wird die Serialisierung benutzerdefinierter Typen wie datetime und UUID, das Streaming von Gigabyte-großen Dateien mit ijson, und Terminal-Syntaxhervorhebung mit rich behandelt.

Wichtigste Punkte
  • json.dumps(data, indent=4) ist seit Python 2.6 in der Stdlib eingebaut — kein Install nötig.
  • Übergib ensure_ascii=False, wenn deine Daten Umlaute, CJK-Zeichen oder Emoji enthalten.
  • Für datetime, UUID oder benutzerdefinierte Klassen verwende den default=-Parameter oder erstelle eine Unterklasse von json.JSONEncoder.
  • separators=(',', ':') entfernt alle Leerzeichen — für Netzwerkübertragung oder URL-Einbettung verwenden.
  • orjson ist 5–10× schneller als die Stdlib und verarbeitet datetime und uuid.UUID nativ.
  • pprint.pprint() gibt Python-Syntax aus (True/None), kein gültiges JSON — niemals für Dateien oder API-Antworten verwenden.
  • Bei JSON-Dateien größer als 50 MB mit ijson streamen statt json.load(), um MemoryError zu vermeiden.

Was ist JSON Pretty Printing?

Pretty Printing verwandelt einen dichten, minimierten JSON-String in ein menschenlesbares Format mit konsistenter Einrückung und Zeilenumbrüchen. Die Transformation ist rein kosmetischer Natur: Die Daten sind identisch, nur die Darstellung ändert sich. Pythons json-Modul erledigt dies vollständig in der Standardbibliothek — nichts zu installieren.

Before · json
After · json
{"id":"usr_9f3a2b","name":"Klaus Müller","roles":["admin","editor"],"prefs":{"theme":"dark","lang":"de"}}
{
    "id": "usr_9f3a2b",
    "name": "Klaus Müller",
    "roles": [
        "admin",
        "editor"
    ],
    "prefs": {
        "theme": "dark",
        "lang": "de"
    }
}

json.dumps() — Die Standardmethode zur JSON-Formatierung

json.dumps() ist seit Python 2.6 Teil der Standardbibliothek — einfach import json, kein Install nötig. Es serialisiert jedes JSON-kompatible Python-Objekt in einen formatierten String. Der entscheidende Parameter ist indent: auf 4 (oder 2) setzen für lesbare Ausgabe.

Python 3.8+ — minimales Beispiel
import json

benutzer = {
    "id": "usr_9f3a2b",
    "name": "Klaus Müller",
    "roles": ["admin", "editor"],
    "prefs": {"theme": "dark", "lang": "de"}
}

print(json.dumps(benutzer, indent=4, ensure_ascii=False))
# Ausgabe:
# {
#     "id": "usr_9f3a2b",
#     "name": "Klaus Müller",
#     "roles": [
#         "admin",
#         "editor"
#     ],
#     "prefs": {
#         "theme": "dark",
#         "lang": "de"
#     }
# }

Für den Produktionseinsatz möchte man oft sort_keys=True (konsistente Ausgabe über mehrere Läufe) und ensure_ascii=False (Nicht-ASCII-Zeichen lesbar halten):

Python 3.8+ — mit sort_keys und ensure_ascii
import json

api_antwort = {
    "timestamp": "2024-05-01T10:30:00Z",
    "status": "success",
    "data": {
        "user_id": "usr_9f3a2b",
        "display_name": "Anna Schmidt",
        "city": "München",
        "score": 4892.5,
        "tags": ["python", "backend", "api"]
    }
}

print(json.dumps(api_antwort, indent=4, sort_keys=True, ensure_ascii=False))
# Ausgabe (Schlüssel sortiert, Umlaute erhalten):
# {
#     "data": {
#         "city": "München",
#         "display_name": "Anna Schmidt",
#         "score": 4892.5,
#         "tags": ["api", "backend", "python"],
#         "user_id": "usr_9f3a2b"
#     },
#     "status": "success",
#     "timestamp": "2024-05-01T10:30:00Z"
# }
Hinweis:json.dumps() gibt einen String zurück. Um formatiertes JSON direkt in eine Datei zu schreiben, verwende json.dump(data, f, indent=4) (ohne das s) — es schreibt in ein Datei-Objekt und vermeidet die Erstellung eines Zwischen-Strings im Speicher.

json.dumps() Parameter-Referenz

Alle Parameter sind optional außer dem Objekt selbst. Die Standardwerte erzeugen kompaktes, ASCII-sicheres JSON — Parameter explizit übergeben für menschenlesbare Ausgabe.

Parameter
Typ
Default
Beschreibung
obj
any
Python-Objekt, das in einen JSON-formatierten String serialisiert werden soll.
indent
int | str | None
None
Leerzeichen pro Einrückungsebene. None = kompakte Einzelzeile, 0 = nur Zeilenumbrüche, 4 = Standard.
sort_keys
bool
False
Dictionary-Schlüssel alphabetisch auf allen verschachtelten Ebenen sortieren.
ensure_ascii
bool
True
Nicht-ASCII-Zeichen als \uXXXX escapen. False setzen, um Unicode-Zeichen unverändert zu erhalten.
separators
tuple | None
None
(item_sep, key_sep) Paar. (",", ":") verwenden für die kompakteste Ausgabe ohne Leerzeichen.
default
callable | None
None
Wird für standardmäßig nicht serialisierbare Typen aufgerufen. TypeError werfen, um den Wert abzulehnen.
allow_nan
bool
True
float("nan") und float("inf") als JS-Literale serialisieren. False setzen, um ValueError zu werfen.

Kompakte JSON-Ausgabe mit dem separators-Parameter

Standardmäßig trennt json.dumps() Elemente mit ", " und Schlüssel von Werten mit ": ". Der separators-Parameter überschreibt beide. Das Übergeben von (',', ':') entfernt alle Leerzeichen und erzeugt das kompakteste gültige JSON — nützlich für Netzwerkübertragung, URL-Einbettung oder das Speichern von JSON in einer Datenbankspalte, wo jedes Byte zählt.

Python 3.8+
import json

payload = {
    "endpoint": "/api/v2/events",
    "filters": {"status": "active", "limit": 100},
    "sort": "desc"
}

# Standard — Leerzeichen nach Trennzeichen (lesbar)
standard_ausgabe = json.dumps(payload)
# {"endpoint": "/api/v2/events", "filters": {"status": "active", "limit": 100}, "sort": "desc"}
# len = 88

# Kompakt — keine Leerzeichen
kompakt_ausgabe = json.dumps(payload, separators=(',', ':'))
# {"endpoint":"/api/v2/events","filters":{"status":"active","limit":100},"sort":"desc"}
# len = 80  (9% kleiner; Ersparnis wächst bei größeren, tief verschachtelten Payloads)

# Kompakt + sortierte Schlüssel für reproduzierbare Cache-Schlüssel oder Content-Hashes
kanonisch = json.dumps(payload, separators=(',', ':'), sort_keys=True)
print(kanonisch)
# {"endpoint":"/api/v2/events","filters":{"limit":100,"status":"active"},"sort":"desc"}
Hinweis:Wenn indent= zusammen mit separators= übergeben wird, steuert das separators-Argument nur die inline-Trennzeichen — Zeilenumbrüche und Einrückung von indent bleiben erhalten. Für kompakte einzeilige Ausgabe indent weglassen (oder None übergeben) und separators=(',', ':') setzen.

Benutzerdefinierte Python-Objekte mit dem default-Parameter serialisieren

Das Standard-json-Modul serialisiert Dicts, Listen, Strings, Zahlen, Booleans und None — wirft aber einen TypeError für jeden anderen Typ. Die zwei häufigsten Problemfälle im Produktionscode sind datetime-Objekte und UUIDs.

Python 3.8+ — TypeError ohne benutzerdefinierte Behandlung
import json
from datetime import datetime, timezone
import uuid

bestellung = {
    "order_id": uuid.uuid4(),            # ❌ TypeError: UUID is not JSON serializable
    "placed_at": datetime.now(timezone.utc),  # ❌ TypeError: datetime is not JSON serializable
    "total_eur": 142.50,
    "items": ["pro-subscription", "addon-storage"]
}

json.dumps(bestellung)  # wirft TypeError

Ansatz 1 — der default=-Parameter

Übergib einen Callable an default=. json.dumps() ruft ihn für jedes Objekt auf, das es nicht verarbeiten kann. Gib eine serialisierbare Darstellung zurück, oder wirf TypeError für Typen, die du nicht explizit unterstützt — unbekannte Typen niemals stillschweigend ignorieren.

Python 3.8+
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal

def json_default(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    if isinstance(obj, uuid.UUID):
        return str(obj)
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj).__name__!r} is not JSON serializable")

bestellung = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_eur": Decimal("142.50"),
    "items": ["pro-subscription", "addon-storage"]
}

print(json.dumps(bestellung, indent=4, default=json_default))
# {
#     "order_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#     "placed_at": "2024-05-01T10:30:00+00:00",
#     "total_eur": 142.5,
#     "items": ["pro-subscription", "addon-storage"]
# }

Ansatz 2 — Unterklasse von json.JSONEncoder

Für wiederverwendbare Kodierungslogik, die über mehrere Module hinweg geteilt wird, ist das Erstellen einer Unterklasse von json.JSONEncoder sauberer als das Herumreichen einer default-Funktion. Überschreibe die default-Methode und rufe super().default(obj) als letzten Fallback auf — das erhält das korrekte Fehlerverhalten für nicht unterstützte Typen.

Python 3.8+
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal

class AppEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, Decimal):
            return float(obj)
        return super().default(obj)  # wirft TypeError für unbekannte Typen

bestellung = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_eur": Decimal("142.50"),
}

# Encoder-Klasse via cls= übergeben
print(json.dumps(bestellung, indent=4, cls=AppEncoder))
# Identische Ausgabe wie beim default=-Ansatz
Hinweis:Immer super().default(obj) aufrufen (oder TypeError explizit werfen) für nicht erkannte Typen. Stillschweigend str(obj) für alles zurückzugeben, wird Objekte korrumpieren, die eigentlich einen Fehler hätten auslösen sollen — ein Bug, der in der Produktion schwer zu verfolgen ist.

Zurückdecodieren — object_hook

Kodieren ist nur die halbe Wahrheit. Um ein benutzerdefiniertes Python-Objekt aus JSON wiederherzustellen, übergib eine object_hook-Funktion an json.loads() oder json.load(). Der Hook wird für jedes dekodierte JSON-Objekt (Dict) aufgerufen und kann einen beliebigen Python-Wert zurückgeben — so entsteht ein vollständiger Encode ↔ Decode-Roundtrip.

Python 3.8+
import json
from datetime import datetime
from dataclasses import dataclass

@dataclass
class Event:
    name: str
    occurred_at: datetime
    user_id: str

def encode_event(obj):
    if isinstance(obj, Event):
        return {
            "__type__": "Event",
            "name": obj.name,
            "occurred_at": obj.occurred_at.isoformat(),
            "user_id": obj.user_id,
        }
    raise TypeError(f"Cannot serialize {type(obj)}")

def decode_event(d):
    if d.get("__type__") == "Event":
        return Event(
            name=d["name"],
            occurred_at=datetime.fromisoformat(d["occurred_at"]),
            user_id=d["user_id"],
        )
    return d

# Kodieren
event = Event("login", datetime(2024, 5, 1, 10, 30), "usr_9f3a2b")
json_str = json.dumps(event, default=encode_event, indent=4)

# Zurück in eine Event-Instanz dekodieren
restored = json.loads(json_str, object_hook=decode_event)
print(type(restored))           # <class 'Event'>
print(restored.occurred_at)     # 2024-05-01 10:30:00
Hinweis:Der object_hook wird für jedes verschachtelte Dict im Dokument aufgerufen — nicht nur auf oberster Ebene. Ein Diskriminator-Feld einschließen (wie "__type__"), damit der Hook benutzerdefinierte Objekte von einfachen Dicts unterscheiden kann, die unverändert bleiben sollen.

pprint — Das alternative Modul (und wann man es nicht verwendet)

Pythons pprint-Modul (Pretty Printer) formatiert Python-Datenstrukturen für die Lesbarkeit im Terminal. Es arbeitet auf geparsten Python-Objekten, nicht auf JSON-Strings — und seine Ausgabe verwendet Python-Syntax, nicht JSON-Syntax.

Python 3.8+
import json, pprint

raw = '{"sensor_id":"s-441","readings":[23.1,23.4,22.9],"unit":"celsius","active":true}'
data = json.loads(raw)

# pprint — gültiges Python repr, KEIN gültiges JSON
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
#  'readings': [23.1, 23.4, 22.9],
#  'unit': 'celsius',
#  'active': True}        ← Python True, nicht JSON true

# json.dumps — gültiges JSON
print(json.dumps(data, indent=4))
# {
#     "sensor_id": "s-441",
#     "readings": [23.1, 23.4, 22.9],
#     "unit": "celsius",
#     "active": true      ← gültiges JSON
# }
Warnung:Die pprint-Ausgabe niemals an einen API-Endpunkt senden oder in eine .json-Datei schreiben — sie wird jeden JSON-Parser, der Standardsyntax erwartet, zum Absturz bringen. Verwende json.dumps(indent=4) für alle Ausgaben, die gültiges JSON sein müssen.

Wann pprint sinnvoll ist: schnelle Terminal-Inspektion von Python-Objekten im REPL oder Debug-Log, besonders wenn das Objekt nicht JSON-serialisierbare Typen enthält (Sets, benutzerdefinierte Klasseninstanzen, Dataclasses vor der Konvertierung).

Wie man eine JSON-Antwort von Requests formatiert

Das häufigste reale Szenario: Man hat eine JSON-Datei auf der Festplatte oder eine HTTP-Antwort von einer API und möchte sie zum Debuggen oder Loggen formatieren. Beide Fälle verwenden den gleichen Ansatz — als Python-Dict parsen, dann mit json.dumps() formatieren.

Aus einer Datei lesen

Python 3.8+
import json

try:
    with open("config.json", "r", encoding="utf-8") as f:
        data = json.load(f)

    # In der Konsole ausgeben
    print(json.dumps(data, indent=4, ensure_ascii=False))

    # Oder die formatierte Version zurück auf die Festplatte schreiben
    with open("config.formatiert.json", "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

except json.JSONDecodeError as e:
    print(f"Ungültiges JSON: {e}")
except FileNotFoundError:
    print(f"Datei nicht gefunden: config.json")

Eine API-Antwort formatieren

Python 3.8+ (erfordert: pip install requests)
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout

def api_ausgeben(url: str) -> None:
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()
        print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
    except HTTPError as e:
        print(f"HTTP {e.response.status_code}: {e}")
    except (ConnectionError, Timeout) as e:
        print(f"Netzwerkfehler: {e}")
    except json.JSONDecodeError:
        print(f"Antwort-Body ist kein JSON:\n{resp.text[:500]}")

api_ausgeben("https://api.github.com/repos/python/cpython")
Hinweis:response.json() parst den Antwort-Body bereits — kein separates json.loads() nötig. Immer raise_for_status() hinzufügen, bevor auf .json() zugegriffen wird, um 4xx/5xx-Fehler abzufangen, bevor sie einen verwirrenden Parse-Fehler verursachen.

Formatierung über die Kommandozeile

Python wird mit json.tool ausgeliefert, einem CLI-Modul zur Formatierung von JSON direkt aus dem Terminal — kein Python-Skript erforderlich. Auf jedem Rechner mit installiertem Python verfügbar.

bash
# Lokale Datei formatieren
python -m json.tool config.json

# API-Antwort durch Formatter leiten
curl -s https://api.github.com/users/gvanrossum | python -m json.tool

# Von stdin formatieren
echo '{"service":"api-gateway","version":"2.1.0","healthy":true}' | python -m json.tool

# Schlüssel alphabetisch sortieren
python -m json.tool --sort-keys data.json

# Benutzerdefinierte Einrückung (Python 3.9+)
python -m json.tool --indent 2 data.json
Hinweis:Python 3.9 hat die Flags --indent und --no-indent hinzugefügt. Für leistungsfähigeres Terminal-JSON-Filtering empfiehlt sich jq — aber python -m json.tool deckt den Formatierungs-Anwendungsfall ohne zusätzliche Abhängigkeiten ab.

Wenn Sie überhaupt kein Terminal haben — etwa beim Einfügen einer Postman-Antwort oder einer Log-Datei — erlaubt der ToolDeck JSON Formatter das Einfügen, Formatieren und Kopieren in einem Schritt mit integrierter Syntaxhervorhebung und Validierung.

Alternative Bibliotheken: orjson und rich

orjson — 5–10× schneller mit nativem Typ-Support

Das Standard- json-Modul ist für die meisten Anwendungsfälle schnell genug, aber wenn man tausende Objekte pro Sekunde serialisiert — Logging-Pipelines, hochdurchsatzige APIs, große Datenexporte — ist orjson 5–10× schneller. Es verarbeitet auch nativ Typen, die die Standardbibliothek ohne eine benutzerdefinierte default-Funktion nicht serialisieren kann: datetime, uuid.UUID, numpy-Arrays und Dataclasses.

bash — Installation
pip install orjson
Python 3.8+
import orjson
from datetime import datetime, timezone
import uuid

event = {
    "event_id": uuid.uuid4(),                  # kein str() nötig — orjson verarbeitet UUID
    "timestamp": datetime.now(timezone.utc),   # kein isoformat() nötig
    "service": "auth-service",
    "level": "INFO",
    "payload": {
        "user_id": "usr_9f3a2b",
        "action": "login",
        "ip": "192.168.1.42",
        "latency_ms": 34
    }
}

# orjson.dumps gibt bytes zurück; .decode() konvertiert zu str
print(orjson.dumps(event, option=orjson.OPT_INDENT_2).decode())
# {
#   "event_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#   "timestamp": "2024-05-01T10:30:00+00:00",
#   "service": "auth-service",
#   ...
# }

Zwei wichtige Hinweise: orjson.dumps() gibt bytes zurück, keinen String — .decode() aufrufen, wenn ein String benötigt wird. Es unterstützt nur 2-Leerzeichen-Einrückung via OPT_INDENT_2; für 4-Leerzeichen-Ausgabe das Standard-json.dumps(indent=4) verwenden.

rich — Syntaxhervorhebung im Terminal

Wenn man regelmäßig JSON im Terminal oder REPL inspiziert, rendert rich farbcodierte, syntaxhervorgehobene Ausgabe, die tief verschachtelte Strukturen auf einen Blick lesbar macht. Schlüssel, Strings, Zahlen und Booleans erhalten je eine eigene Farbe — viel einfacher zu scannen als eine Wand monochromen Texts. Es ist ein reines Debug-Tool, nicht für die Serialisierung in der Produktion.

bash — Installation
pip install rich
Python 3.8+
from rich import print_json
import json

# print_json() akzeptiert einen JSON-String
raw = '{"event":"login","user_id":"usr_9f3a2b","timestamp":"2024-05-01T10:30:00Z","success":true,"meta":{"ip":"192.168.1.42","attempts":1}}'
print_json(raw)

# Um ein Python-Dict zu formatieren, zuerst in String konvertieren
data = {
    "status": "success",
    "count": 42,
    "tags": ["python", "api", "backend"]
}
print_json(json.dumps(data))
Warnung:rich.print_json() gibt ANSI-Escape-Codes für Terminal-Farbe aus — diese Ausgabe niemals erfassen und in eine .json-Datei schreiben oder als API-Antwort senden. Für maschinenlesbare Ausgabe json.dumps(indent=4) verwenden.

simplejson — Drop-in-Kompatibilitätsersatz

simplejson ist die Bibliothek, die Pythons Standard-json-Modul wurde — sie wird weiterhin unabhängig gepflegt und ist der Stdlib bei kleineren Features voraus. Es ist ein echter Drop-in-Ersatz: Den Import austauschen, und der Rest des Codes bleibt unverändert. Nützlich, wenn man Decimal-Support ohne benutzerdefinierten Encoder braucht, oder wenn man ältere Python-Umgebungen unterstützt.

bash — Installation
pip install simplejson
Python 3.8+
import simplejson as json  # identische API wie stdlib
from decimal import Decimal

bestellung = {
    "item": "API-Abonnement Berlin",
    "price": Decimal("49.99"),   # stdlib json würde hier TypeError werfen
    "quantity": 3,
}

# simplejson serialisiert Decimal nativ — kein default= nötig
print(json.dumps(bestellung, indent=4, use_decimal=True))
# {
#     "item": "API-Abonnement Berlin",
#     "price": 49.99,
#     "quantity": 3
# }
Hinweis:Für reine Performance ist orjson die bessere Wahl.simplejson wählen, wenn native Decimal-Serialisierung ohne benutzerdefinierten Encoder benötigt wird, oder wenn eine Codebasis gepflegt wird, die es bereits verwendet.

Große JSON-Dateien ohne Speicherprobleme verarbeiten

json.load() liest die gesamte Datei in den Speicher, bevor auf ein einzelnes Feld zugegriffen werden kann. Bei einer Datei mit Millionen von Datensätzen oder einem Payload über einem Gigabyte führt das zu einem MemoryError — oder zwingt den Prozess im besten Fall, auf die Festplatte auszulagern und sehr langsam zu werden.

Streaming mit ijson

ijson ist ein streaming JSON-Parser, der Elemente einzeln aus einem Datei-Objekt generiert. Man iteriert über Array-Elemente, ohne den gesamten Datensatz im Speicher zu halten — der Spitzenspeicherverbrauch bleibt proportional zu einem einzelnen Objekt, nicht zur Dateigröße.

bash — Installation
pip install ijson
Python 3.8+
import ijson
from decimal import Decimal

# events.json Struktur: {"events": [...Millionen von Objekten...]}
gesamtumsatz = Decimal("0")
login_anzahl = 0

with open("events.json", "rb") as f:   # ijson erfordert Binärmodus
    for event in ijson.items(f, "events.item"):
        if event.get("type") == "purchase":
            gesamtumsatz += Decimal(str(event["amount_eur"]))
        elif event.get("type") == "login":
            login_anzahl += 1

print(f"Umsatz: {gesamtumsatz:.2f} EUR  |  Logins: {login_anzahl}")
# Verarbeitet eine 2-GB-Datei mit ~30 MB Spitzenspeicherverbrauch
Hinweis:Von json.load() zu ijson wechseln, wenn die Datei ungefähr 50–100 MB überschreitet. Unterhalb dieser Schwelle ist json.load() einfacher und deutlich schneller, da es intern einen C-Extension-Parser verwendet. Über 100 MB überwiegen die Speichereinsparungen durch Streaming den zusätzlichen Overhead.

NDJSON — ein JSON-Objekt pro Zeile

NDJSON (Newline Delimited JSON, auch JSON Lines oder .jsonl genannt) speichert ein vollständiges JSON-Objekt pro Zeile. Log-Exporter, Kafka-Consumer und Datenpipelines produzieren dieses Format häufig, weil jede Zeile unabhängig angehängt und gelesen werden kann. Die Standardbibliothek verarbeitet es ohne zusätzliche Abhängigkeiten.

Python 3.8+
import json
from pathlib import Path

# NDJSON schreiben — ein Event pro Zeile
events = [
    {"ts": "2024-05-01T10:00:00Z", "user": "usr_9f3a2b", "action": "login"},
    {"ts": "2024-05-01T10:01:03Z", "user": "usr_9f3a2b", "action": "purchase", "sku": "pro-plan"},
    {"ts": "2024-05-01T10:15:42Z", "user": "usr_4ab1d9", "action": "login"},
]

with open("events.ndjson", "w", encoding="utf-8") as f:
    for event in events:
        f.write(json.dumps(event, ensure_ascii=False) + "\n")

# NDJSON lesen — konstanter Speicher, unabhängig von der Dateigröße
kauf_anzahl = 0
with open("events.ndjson", "r", encoding="utf-8") as f:
    for zeile in f:
        zeile = zeile.strip()
        if not zeile:           # leere Zeilen überspringen
            continue
        event = json.loads(zeile)
        if event.get("action") == "purchase":
            kauf_anzahl += 1
            print(f"{event['ts']} — {event['user']} kaufte {event['sku']}")

Häufige Fehler

Diese vier Fehler sehe ich in fast jeder Code-Review, die JSON-Serialisierung betrifft — besonders bei Entwicklern, die von JavaScript kommen, wo JSON.stringify die Kodierung automatisch übernimmt.

print(data) statt json.dumps() verwenden

Problem: print() auf einem Dict verwendet Python repr — die Ausgabe zeigt True/None (Python-Syntax), nicht true/null (JSON-Syntax). Es ist kein gültiges JSON.

Lösung: Immer json.dumps(data, indent=4) für gültige, lesbare JSON-Ausgabe verwenden.

Before · Python
After · Python
data = {"active": True, "count": None}
print(data)
# {'active': True, 'count': None}
print(json.dumps(data, indent=4))
# {
#     "active": true,
#     "count": null
# }
ensure_ascii=False bei Nicht-ASCII-Text vergessen

Problem: Sonderzeichen (Umlaute, CJK, Emoji) werden zu \\uXXXX-Sequenzen escaped, was die Ausgabe unlesbar macht.

Lösung: ensure_ascii=False übergeben, um die originalen Unicode-Zeichen zu erhalten.

Before · Python
After · Python
user = {"name": "Klaus Müller", "city": "München"}
json.dumps(user, indent=2)
# {"name": "Klaus M\u00fcller", "city": "M\u00fcnchen"}
json.dumps(user, indent=2, ensure_ascii=False)
# {"name": "Klaus Müller", "city": "München"}
json.dumps() zum Schreiben in eine Datei verwenden

Problem: json.dumps() gibt einen String zurück; man braucht dann einen separaten f.write()-Aufruf, was einen unnötigen Zwischen-String erzeugt.

Lösung: json.dump(data, f, indent=4) verwenden — schreibt direkt in das Datei-Objekt.

Before · Python
After · Python
with open("out.json", "w") as f:
    f.write(json.dumps(data, indent=4))
with open("out.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=4, ensure_ascii=False)
Mit pprint formatieren und gültiges JSON erwarten

Problem: pprint.pprint() verwendet Python-Syntax (True, None, einfache Anführungszeichen), die JSON-Parser ablehnen.

Lösung: json.dumps(indent=4) für jede Ausgabe verwenden, die als JSON parsebar sein muss.

Before · Python
After · Python
import pprint
pprint.pprint({"running": True, "last_error": None})
# {'running': True, 'last_error': None}
import json
print(json.dumps({"running": True, "last_error": None}, indent=4))
# {"running": true, "last_error": null}

Methodenvergleich — json.dumps, orjson, simplejson, rich

json.dumps() für alltägliche Formatierung und Dateischreibvorgänge verwenden — es deckt 95% der Anwendungsfälle ohne Abhängigkeiten ab. Auf orjson zurückgreifen, wenn in einem Hot Path serialisiert wird oder wenn Objekte datetime- und UUID-Felder enthalten.simplejson verwenden, wenn Drop-in-Stdlib-Kompatibilität mit Decimal-Support direkt aus der Box benötigt wird. rich.print_json() und pprint streng für die lokale Terminal-Inspektion reservieren — keines der beiden erzeugt maschinenlesbare Ausgabe.

Methode
Ausgabe
Valid JSON
Geschwindigkeit
Non-ASCII
Custom Types
Installation
json.dumps(indent=4)
String
Standard
ensure_ascii=False
default= / JSONEncoder
Integriert
json.dump(f, indent=4)
Datei
Standard
ensure_ascii=False
default= / JSONEncoder
Integriert
pprint.pprint()
Python repr
Standard
Nativ
✅ (beliebiges repr)
Integriert
orjson.dumps(OPT_INDENT_2)
Bytes
5–10× schneller
Nativ
datetime, UUID, numpy
pip install orjson
python -m json.tool
CLI stdout
Standard
Integriert
simplejson.dumps()
String
~1.5× schneller
ensure_ascii=False
Decimal nativ
pip install simplejson
rich.print_json()
Nur Terminal
✅ (Eingabe)
Standard
pip install rich

Häufig gestellte Fragen

Wie formatiere ich JSON in Python lesbar?

Rufe json.dumps(data, indent=4) auf. Der indent-Parameter legt die Anzahl der Leerzeichen pro Verschachtelungsebene fest. Importiere zuerst das json-Modul — es ist in der Standardbibliothek von Python enthalten, kein pip install erforderlich. Übergib ensure_ascii=False, wenn deine Daten Umlaute, CJK-Zeichen oder andere nicht-ASCII-Zeichen enthalten.

python
import json

benutzer = {"username": "kmueller", "plan": "enterprise", "berechtigungen": ["lesen", "schreiben", "deploy"]}
print(json.dumps(benutzer, indent=4, ensure_ascii=False))

Was ist der Unterschied zwischen json.dumps() und json.dump()?

json.dumps() (mit "s") gibt einen formatierten String im Speicher zurück. json.dump() (ohne "s") schreibt direkt in ein dateiähnliches Objekt — übergib das geöffnete Datei-Handle als zweites Argument. Um formatiertes JSON auf die Festplatte zu schreiben, ist json.dump(data, f, indent=4) idiomatisch und vermeidet die Erstellung eines Zwischen-Strings.

python
# dumps → String im Speicher
formatiert = json.dumps(data, indent=4)

# dump → direkt in Datei schreiben
with open('ausgabe.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=4)

Warum zeigt json.dumps() \u00fc\u00e4\u00f6 statt der eigentlichen Zeichen?

Standardmäßig escaped ensure_ascii=True jeden nicht-ASCII-Zeichen zu einer \uXXXX-Sequenz. Setze ensure_ascii=False, um die originalen Unicode-Zeichen zu erhalten. Dies ist besonders wichtig für Namen, Adressen und nutzergenerierte Inhalte mit deutschen Umlauten oder anderen nicht-lateinischen Schriften.

python
data = {"stadt": "München", "gruesse": "Grüß Gott", "land": "Österreich"}

# Standard — escaped
json.dumps(data, indent=4)
# {"stadt": "M\u00fcnchen", "gruesse": "Gr\u00fc\u00df Gott", ...}

# Lesbar
json.dumps(data, indent=4, ensure_ascii=False)
# {"stadt": "München", "gruesse": "Grüß Gott", "land": "Österreich"}

Wie formatiere ich einen JSON-String (kein Dict)?

Zuerst den String mit json.loads() parsen, dann mit json.dumps() formatieren. Beide Aufrufe können für eine schnelle Terminal-Inspektion in einer Zeile verkettet werden.

python
import json

raw = '{"endpoint":"/api/v2/benutzer","timeout":30,"wiederholen":true}'
print(json.dumps(json.loads(raw), indent=4))

Kann ich pprint verwenden, um JSON in Python zu formatieren?

pprint.pprint() erzeugt Python-Objekt-Darstellung, kein gültiges JSON. Es verwendet True/False/None (Python-Syntax) statt true/false/null (JSON-Syntax). Übergib die pprint-Ausgabe niemals an eine API oder einen JSON-Parser — verwende json.dumps(indent=4) für alles, das gültiges JSON sein muss.

python
import pprint, json

data = {"aktiv": True, "punktzahl": None}

pprint.pprint(data)     # {'aktiv': True, 'punktzahl': None}  ← kein JSON
json.dumps(data, indent=4)  # {"aktiv": true, "punktzahl": null}  ← gültiges JSON

Wie sortiere ich JSON-Schlüssel alphabetisch in Python?

Füge sort_keys=True zu json.dumps() hinzu. Für die Kommandozeile verwende python -m json.tool --sort-keys data.json. Sortierte Schlüssel machen JSON-Diffs lesbar und helfen, geänderte Werte auf einen Blick zu erkennen.

python
import json

server = {"workers": 4, "host": "0.0.0.0", "port": 8080, "debug": False}
print(json.dumps(server, indent=4, sort_keys=True))
# {
#     "debug": false,
#     "host": "0.0.0.0",
#     "port": 8080,
#     "workers": 4
# }

Python gibt Ihnen volle Kontrolle — eigene Serialisierer, Streaming, Pipeline-Integration. Wenn Sie nur einen formatierten Snippet inspizieren oder teilen möchten, ist der ToolDeck JSON Formatter der schnellere Weg: JSON einfügen und ein eingerücktes, hervorgehobenes Ergebnis ohne Umgebungseinrichtung erhalten.

Verwandte Tools

Auch verfügbar in:GoJavaScriptBash
MS
Maria SantosBackend Developer

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.

DV
Dmitri VolkovTechnischer Prüfer

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.