JSON Formatter JavaScript — JSON.stringify()
Nutze das kostenlose JSON Formatter & Beautifier direkt im Browser – keine Installation erforderlich.
JSON Formatter & Beautifier online testen →Wenn ich API-Antworten in Node.js debugge, ist ein Haufen minimiertes JSON das Erste, was mich aufhält — ein einziger Aufruf von JSON.stringify(data, null, 2) und die Struktur wird sofort lesbar. Um JSON in JavaScript zu formatieren, brauchst du nichts außer der Laufzeitumgebung: JSON.stringify ist in jeden Browser und jede Node.js-Umgebung eingebaut, keine Installation nötig. Wenn du nur ein schnelles Ergebnis ohne Code brauchst, erledigt der JSON Formatter von ToolDeck das sofort. Dieser Leitfaden deckt alles Praktische ab: den space-Parameter, Replacer-Arrays und -Funktionen, den Umgang mit Date, BigInt und zirkulären Referenzen, das Lesen und Schreiben von JSON-Dateien in Node.js (18+), CLI-Pretty-Printing und die fast-json-stringify-Bibliothek für die Serialisierung im Produktionsbetrieb.
- ✓JSON.stringify(data, null, 2) ist in jeden Browser und Node.js eingebaut — keine Installation erforderlich.
- ✓Der replacer-Parameter akzeptiert ein Array (Schlüssel-Whitelist) oder eine Funktion (Werte transformieren) — nutze ihn zum Maskieren sensibler Felder.
- ✓Date-Objekte werden automatisch über toJSON() → ISO 8601-String serialisiert; BigInt wirft einen TypeError und erfordert einen benutzerdefinierten Replacer.
- ✓Zirkuläre Referenzen werfen TypeError — behebe das mit einem WeakSet in einer Replacer-Funktion oder der flatted-Bibliothek.
- ✓Für CLI-Pretty-Printing nutze node -p "JSON.stringify(require('./file.json'),null,2)" — keine zusätzlichen Tools nötig.
Was ist JSON-Formatierung?
JSON-Formatierung (auch Pretty-Printing genannt) verwandelt einen kompakten, minimierten JSON-String in ein für Menschen lesbares Layout mit einheitlicher Einrückung und Zeilenumbrüchen. Die zugrundeliegenden Daten sind identisch — nur der Whitespace ändert sich. Kompaktes JSON ist optimal für die Netzwerkübertragung, wo jedes Byte zählt; formatiertes JSON ist optimal für Debugging, Code-Reviews und Log-Inspektion. JavaScripts JSON.stringify() erledigt beides in einem einzigen Aufruf, indem man den space-Parameter umschaltet.
{"orderId":"ord_8f2a91bc","status":"shipped","items":[{"sku":"HDMI-4K-2M","qty":2,"unitPrice":12.99}],"total":25.98}{
"orderId": "ord_8f2a91bc",
"status": "shipped",
"items": [
{
"sku": "HDMI-4K-2M",
"qty": 2,
"unitPrice": 12.99
}
],
"total": 25.98
}JSON.stringify() — Der eingebaute Formatter
JSON.stringify() ist eine globale Funktion in jeder JavaScript-Umgebung — Browser, Node.js, Deno, Bun — ohne Import. Das dritte Argument, space, steuert die Einrückung: Übergib eine Zahl für diese Anzahl Leerzeichen pro Ebene oder den String '\t' für Tabs. Lässt du ihn weg (oder übergibst null), erhältst du kompakte einzeilige Ausgabe.
const serverConfig = {
host: "api.payments.internal",
port: 8443,
workers: 4,
tls: { enabled: true, cert: "/etc/ssl/certs/api.pem" },
rateLimit: { requestsPerMinute: 1000, burst: 50 }
}
console.log(JSON.stringify(serverConfig, null, 2))
// {
// "host": "api.payments.internal",
// "port": 8443,
// "workers": 4,
// "tls": {
// "enabled": true,
// "cert": "/etc/ssl/certs/api.pem"
// },
// "rateLimit": {
// "requestsPerMinute": 1000,
// "burst": 50
// }
// }Der space-Parameter akzeptiert entweder eine Zahl (1–10 Leerzeichen) oder einen String. Ein Tab-Zeichen erzeugt Ausgaben, die viele Editoren und Diff-Tools bevorzugen. Du kannst auch alle drei Parameter kombinieren — hier ist ein Muster, das ich beim Schreiben von formatiertem JSON in Konfigurationsdateien verwende:
const telemetryEvent = {
eventId: "evt_3c7f9a2b",
service: "checkout-api",
severity: "warn",
latencyMs: 342,
region: "eu-west-1",
tags: ["payment", "timeout", "retry"]
}
// 2-Leerzeichen-Einrückung (am häufigsten in JS-Projekten)
JSON.stringify(telemetryEvent, null, 2)
// Tab-Einrückung (von manchen Lintern und Config-Tools bevorzugt)
JSON.stringify(telemetryEvent, null, '\t')
// Kompakt — kein Whitespace (für Netzwerkübertragung)
JSON.stringify(telemetryEvent)
// {"eventId":"evt_3c7f9a2b","service":"checkout-api",...}undefined-, Funktions- und Symbol-Werte werden stillschweigend aus der Ausgabe ausgelassen. Ist ein Property-Wert undefined, erscheint dieser Schlüssel überhaupt nicht im serialisierten String — das ist eine häufige Fehlerquelle beim Loggen von Objekten mit optionalen Feldern.Replacer-Funktionen — Ausgabe filtern und transformieren
Das zweite Argument für JSON.stringify() ist der Replacer. Er kommt in zwei Formen: ein Array, das bestimmte Schlüssel auf die Whitelist setzt, oder eine Funktion, die für jedes Schlüssel/Wert-Paar aufgerufen wird und Werte filtern, transformieren oder redigieren kann. Die Array-Form nutze ich, wenn ich schnell eine Teilmenge brauche, die Funktionsform, wenn ich sensible Daten vor dem Loggen maskieren muss.
Array-Replacer — Bestimmte Schlüssel auf die Whitelist setzen
const order = {
orderId: "ord_8f2a91bc",
customer: {
id: "usr_4421",
email: "l.bauer@beispiel.de",
passwordHash: "bcrypt:$2b$12$XKzV..."
},
items: [{ sku: "HDMI-4K-2M", qty: 2, unitPrice: 12.99 }],
createdAt: "2026-03-10T14:22:00Z"
}
// Nur sichere Felder in die Log-Ausgabe aufnehmen
const safeLog = JSON.stringify(order, ["orderId", "items", "createdAt"], 2)
// {
// "orderId": "ord_8f2a91bc",
// "items": [{ "sku": "HDMI-4K-2M", "qty": 2, "unitPrice": 12.99 }],
// "createdAt": "2026-03-10T14:22:00Z"
// }
// passwordHash und customer.email werden ausgeschlossenFunktions-Replacer — Werte transformieren
const auditRecord = {
requestId: "req_7d2e91",
user: { id: "usr_4421", email: "l.bauer@beispiel.de", apiKey: "sk-live-eKx9..." },
action: "update_billing",
timestamp: new Date("2026-03-10T14:22:00Z"),
durationMs: 87
}
function safeReplacer(key, value) {
// Felder redigieren, die wie Geheimnisse oder PII aussehen
if (key === "apiKey") return "[REDACTED]"
if (key === "email") return value.replace(/(?<=.{2}).+(?=@)/, "***")
return value
}
console.log(JSON.stringify(auditRecord, safeReplacer, 2))
// {
// "requestId": "req_7d2e91",
// "user": { "id": "usr_4421", "email": "l.***@beispiel.de", "apiKey": "[REDACTED]" },
// "action": "update_billing",
// "timestamp": "2026-03-10T14:22:00.000Z",
// "durationMs": 87
// }this aufgerufen, das auf das Objekt mit dem aktuellen Schlüssel zeigt. Der allererste Aufruf übergibt einen leeren String als Schlüssel und den gesamten zu serialisierenden Wert — gib ihn unverändert zurück, um mit der normalen Serialisierung fortzufahren.Umgang mit nicht serialisierbaren Typen
Nicht alle JavaScript-Werte lassen sich sauber auf JSON abbilden. Zu wissen, wie sich jeder Typ verhält, verhindert stillen Datenverlust und unerwartete Laufzeitfehler im Produktionscode.
Date — Automatisch über toJSON()
Date-Objekte implementieren eine toJSON()-Methode, die einen ISO 8601-String zurückgibt. JSON.stringify() ruft toJSON() automatisch vor der Serialisierung auf, sodass kein benutzerdefinierter Umgang erforderlich ist.
const webhook = {
eventType: "payment.succeeded",
occurredAt: new Date("2026-03-10T14:22:00Z"),
processedAt: new Date()
}
JSON.stringify(webhook, null, 2)
// {
// "eventType": "payment.succeeded",
// "occurredAt": "2026-03-10T14:22:00.000Z",
// "processedAt": "2026-03-10T14:22:01.347Z"
// }
// Jedes Objekt mit einer toJSON()-Methode wird gleich behandelt:
const custom = { toJSON: () => "custom-value", hidden: 42 }
JSON.stringify(custom) // '"custom-value"'Custom Classes — toJSON() implementieren
Jede Klasse kann eine toJSON()-Methode implementieren, und JSON.stringify() ruft sie automatisch während der Serialisierung auf. Das ist sauberer als ein globaler Replacer für Domain-Typen, die in der gesamten Codebasis vorkommen.
class Money {
constructor(amount, currency) {
this.amount = amount
this.currency = currency
}
toJSON() {
// Wird automatisch von JSON.stringify aufgerufen
return { amount: this.amount, currency: this.currency, formatted: `${this.currency} ${this.amount.toFixed(2)}` }
}
}
class OrderId {
constructor(id) { this.id = id }
toJSON() { return this.id } // Als einfachen String serialisieren
}
const invoice = {
invoiceId: new OrderId('inv_8f2a91bc'),
subtotal: new Money(199.00, 'EUR'),
tax: new Money(15.92, 'EUR'),
issuedAt: new Date('2026-03-10T14:22:00Z')
}
JSON.stringify(invoice, null, 2)
// {
// "invoiceId": "inv_8f2a91bc",
// "subtotal": { "amount": 199, "currency": "EUR", "formatted": "EUR 199.00" },
// "tax": { "amount": 15.92, "currency": "EUR", "formatted": "EUR 15.92" },
// "issuedAt": "2026-03-10T14:22:00.000Z"
// }toJSON() hat Vorrang vor der Replacer-Funktion. Sind beide vorhanden, wird toJSON() zuerst ausgeführt — der Replacer erhält den bereits konvertierten Wert, nicht die ursprüngliche Klasseninstanz.BigInt — TypeError ohne Replacer
// Das wirft: TypeError: Do not know how to serialize a BigInt
// JSON.stringify({ sessionId: 9007199254741234n })
// Lösung: BigInt im Replacer in einen String konvertieren
function bigIntReplacer(_key, value) {
return typeof value === 'bigint' ? value.toString() : value
}
const metrics = {
requestCount: 9007199254741234n, // überschreitet Number.MAX_SAFE_INTEGER
service: "ingestion-worker",
region: "eu-central-1"
}
JSON.stringify(metrics, bigIntReplacer, 2)
// {
// "requestCount": "9007199254741234",
// "service": "ingestion-worker",
// "region": "eu-central-1"
// }Zirkuläre Referenzen — TypeError ohne Seen-Set
// Das wirft: TypeError: Converting circular structure to JSON
// const node = { id: "n1" }; node.self = node; JSON.stringify(node)
// Lösung: gesehene Objekte mit einem WeakSet verfolgen
function circularReplacer() {
const seen = new WeakSet()
return function (_key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]'
seen.add(value)
}
return value
}
}
const parent = { id: "node_parent", label: "root" }
const child = { id: "node_child", parent }
parent.child = child // zirkulär
JSON.stringify(parent, circularReplacer(), 2)
// {
// "id": "node_parent",
// "label": "root",
// "child": { "id": "node_child", "parent": "[Circular]" }
// }
// Alternativ: npm install flatted
// import { stringify } from 'flatted'
// stringify(parent) // behandelt zirkuläre Referenzen nativJSON.stringify() Parameter-Referenz
Alle drei Parameter werden in jeder modernen JavaScript-Laufzeitumgebung gut unterstützt. Die Standardwerte erzeugen kompaktes, einzeiliges JSON — übergib Parameter explizit für lesbare Ausgabe.
JSON aus einer Datei und API-Antwort formatieren
In Node.js (18+) musst du oft eine JSON-Konfigurationsdatei neu formatieren oder eine API-Antwort für das Debugging pretty-printen. Beide Muster verwenden denselben zweistufigen Ansatz: den Rohtext mit JSON.parse() parsen, dann mit JSON.stringify() neu serialisieren.
Eine JSON-Konfigurationsdatei lesen und neu schreiben
import { readFileSync, writeFileSync } from 'fs'
try {
const raw = readFileSync('./config/database.json', 'utf8')
const config = JSON.parse(raw)
writeFileSync('./config/database.json', JSON.stringify(config, null, 2))
console.log('Konfiguration erfolgreich neu formatiert')
} catch (err) {
console.error('Fehler beim Neu-Formatieren der Konfiguration:', err.message)
// JSON.parse wirft SyntaxError, wenn die Datei ungültiges JSON enthält
// readFileSync wirft ENOENT, wenn die Datei nicht existiert
}Asynchrones Datei-Reformat (fs/promises)
import { readFile, writeFile } from 'fs/promises'
async function reformatJson(filePath) {
const raw = await readFile(filePath, 'utf8')
const parsed = JSON.parse(raw)
const formatted = JSON.stringify(parsed, null, 2)
await writeFile(filePath, formatted, 'utf8')
return { keys: Object.keys(parsed).length }
}
// Verwendung
const { keys } = await reformatJson('./config/feature-flags.json')
console.log(`${keys} Top-Level-Schlüssel neu formatiert`)JSON aus einer fetch()-Antwort pretty-printen
Wenn du einen API-Client in Node.js 18+ oder dem Browser entwickelst oder debuggst, ist das Pretty-Printing des Antwort-Body der schnellste Weg, um zu verstehen, was der Server zurückgegeben hat. Das Standardmuster ist response.json() (geparster Objekt) in JSON.stringify(). Benötigst du zuerst den Raw-String — zum Beispiel um einen Hash zu berechnen oder ihn wörtlich zu loggen — verwende response.text() dann JSON.parse().
// Muster 1: response.json() → pretty print
async function debugEndpoint(url) {
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` }
})
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`)
const data = await res.json()
console.log(JSON.stringify(data, null, 2))
}
await debugEndpoint('https://api.stripe.com/v1/charges?limit=3')// Muster 2: response.text() → parse → format
// Nützlich, wenn du die Rohantwort UND die pretty-geprinte Version loggen möchtest
async function inspectRawResponse(url) {
const res = await fetch(url)
const raw = await res.text()
console.log('Länge der Rohantwort:', raw.length)
try {
const parsed = JSON.parse(raw)
console.log('Formatiert:')
console.log(JSON.stringify(parsed, null, 2))
} catch {
console.error('Antwort ist kein gültiges JSON:', raw.slice(0, 200))
}
}Pretty Printing über die Kommandozeile
Node.js bringt genug Funktionalität mit, um JSON vom Terminal aus pretty-printen zu können, ohne zusätzliche Tools. Diese Einzeiler sind in CI-Skripten, Deployment-Pipelines und Shell-Aliasen nützlich. Für noch schnellere interaktive Nutzung installiere jq — den de-facto-Standard für JSON-Manipulation auf der Kommandozeile.
# package.json mit node -p (print) pretty-printen
node -p "JSON.stringify(require('./package.json'), null, 2)"
# Aus stdin pretty-printen (pipe-freundlich, funktioniert in CI)
echo '{"port":3000,"env":"production"}' | node -e "
const d = require('fs').readFileSync(0, 'utf8')
console.log(JSON.stringify(JSON.parse(d), null, 2))
"
# Eine gespeicherte API-Antwort pretty-printen
cat api-response.json | node -e "
process.stdin.setEncoding('utf8')
let s = ''
process.stdin.on('data', c => s += c)
process.stdin.on('end', () => console.log(JSON.stringify(JSON.parse(s), null, 2)))
"# Python-Fallback (vorinstalliert auf macOS und den meisten Linux-Distributionen)
cat api-response.json | python3 -m json.tool
# jq — schnellstes und funktionsreichstes Tool (brew install jq / apt install jq)
cat api-response.json | jq .
# jq — in einem Schritt pretty-printen und filtern
cat api-response.json | jq '.data.users[] | {id, email}'"type": "module" in package.json), ist require() in Einzeilern nicht verfügbar. Verwende --input-type=module und fs.readFileSync stattdessen oder wechsle zu node -e mit einem CommonJS-Snippet wie oben gezeigt.Wenn du gar nicht im Terminal bist — du fügst eine Postman-Antwort oder eine Log-Datei ein — ermöglicht dir der JSON Formatter von ToolDeck das Einfügen, Formatieren und Kopieren in einem Schritt mit Syntaxhervorhebung und eingebauter Validierung.
Hochleistungs-Alternative — fast-json-stringify
fast-json-stringify generiert eine dedizierte Serialisierungsfunktion aus einem JSON Schema. Da es die Form der Daten im Voraus kennt, kann es Typprüfungen überspringen und String-Konkatenation statt rekursivem Abstieg verwenden — Benchmarks zeigen typischerweise einen 2–5×-Durchsatzvorteil gegenüber JSON.stringify() bei großen, repetitiven Payloads. Ich verwende es in hochfrequentierten API-Routen, wo Serialisierungskosten in Profiler-Traces auftauchen.
npm install fast-json-stringify
import fastJson from 'fast-json-stringify'
const serializeTelemetryEvent = fastJson({
title: 'TelemetryEvent',
type: 'object',
properties: {
eventId: { type: 'string' },
service: { type: 'string' },
severity: { type: 'string', enum: ['info', 'warn', 'error'] },
latencyMs: { type: 'integer' },
timestamp: { type: 'string' },
region: { type: 'string' }
},
required: ['eventId', 'service', 'severity', 'latencyMs', 'timestamp']
})
const event = {
eventId: 'evt_3c7f9a2b',
service: 'checkout-api',
severity: 'warn',
latencyMs: 342,
timestamp: new Date().toISOString(),
region: 'eu-central-1'
}
const json = serializeTelemetryEvent(event)
// '{"eventId":"evt_3c7f9a2b","service":"checkout-api","severity":"warn",...}'fast-json-stringify ist für die Produktions-Serialisierung strukturierter Daten konzipiert — es erzeugt immer kompakte Ausgaben (kein Pretty-Printing). Für menschenlesbare Ausgaben während der Entwicklung verwende JSON.stringify(data, null, 2) wie gewohnt.Terminal-Ausgabe mit Syntax-Highlighting
Node.js' eingebautes util.inspect() erzeugt farbige, für Menschen lesbare Ausgaben, die für die Terminal-Anzeige optimiert sind. Es behandelt zirkuläre Referenzen und BigInt nativ und rendert verschachtelte Objekte rekursiv bis zu beliebiger Tiefe. Die Ausgabe ist kein gültiges JSON — sie verwendet JavaScript-Syntax (z.B. true statt true, rendert aber Funktionen und Symbols anstatt sie auszulassen), was es ideal für Node.js-Debugging-Skripte, aber ungeeignet für API-Antworten oder Dateiausgaben macht.
import { inspect } from 'util'
const payload = {
requestId: "req_7d2e91",
user: { id: "usr_4421", roles: ["admin", "billing"] },
metadata: { ipAddress: "203.0.113.42", userAgent: "Mozilla/5.0" },
createdAt: new Date()
}
// depth: null → alle verschachtelten Ebenen aufklappen; colors: true → ANSI-Terminalfarben
console.log(inspect(payload, { colors: true, depth: null }))util.inspect() nicht für JSON, das in Dateien geschrieben, über das Netzwerk gesendet oder in einer Datenbank gespeichert wird. Seine Ausgabe ist kein gültiges JSON und verursacht Parse-Fehler in jedem nachgelagerten System, das JSON.parse() darauf aufruft. Reserviere es nur für interaktives Terminal-Debugging.Arbeiten mit großen JSON-Dateien
JSON.parse() lädt die gesamte Datei in den Speicher, bevor sie geparst wird — für kleine Payloads in Ordnung, aber unpraktisch für Dateien über 50–100 MB wie Datenbankexporte, Anwendungs-Log-Dumps oder Analyse-Batches. Für diese Fälle ermöglichen Node.js Streams und die stream-json-Bibliothek die Verarbeitung von Datensätzen einzeln, ohne den Heap zu sprengen.
Streaming-Parsing mit stream-json
npm install stream-json
import { pipeline } from 'stream/promises'
import { createReadStream } from 'fs'
import { parser } from 'stream-json'
import { streamArray } from 'stream-json/streamers/StreamArray.js'
// events.json = Array mit Millionen von Objekten — wird nie vollständig in den Speicher geladen
await pipeline(
createReadStream('./events.json'),
parser(),
streamArray(),
async function* (source) {
for await (const { value: event } of source) {
if (event.severity === 'error') {
console.log(JSON.stringify(event, null, 2))
}
}
}
)NDJSON / JSON Lines — Keine zusätzlichen Abhängigkeiten
NDJSON (Newline Delimited JSON) speichert ein JSON-Objekt pro Zeile und ist in Kafka-Exporten, BigQuery-Ausgaben und strukturierten Log-Pipelines verbreitet. Node.js' eingebautes readline verarbeitet es ohne Drittanbieter-Pakete.
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Format: ein JSON-Objekt pro Zeile (Logs, Kafka-Exporte, BigQuery)
const rl = createInterface({
input: createReadStream('./logs.ndjson'),
crlfDelay: Infinity
})
for await (const line of rl) {
if (!line.trim()) continue
const entry = JSON.parse(line)
if (entry.level === 'error') {
console.log(JSON.stringify(entry, null, 2))
}
}JSON.parse() zu Streaming, wenn deine JSON-Datei 50–100 MB überschreitet oder wenn du einen unbegrenzten Stream verarbeitest (Kafka, Log-Pipeline). Für NDJSON / JSON Lines verwende readline — es erfordert keine zusätzlichen Abhängigkeiten.Häufige Fehler
Diese vier Fehler tauchen immer wieder in Code-Reviews und Produktions-Bug-Reports auf. Jeder involviert ein subtiles Verhalten von JSON.stringify(), das leicht zu übersehen und im Nachhinein schwer zu debuggen ist.
Problem: Objekt-Properties mit undefined-Werten werden vollständig aus der JSON-Ausgabe ausgelassen — es gibt keine Warnung oder keinen Fehler. Das verursacht unsichtbaren Datenverlust, wenn optionale Felder im Objekt vorhanden sind.
Lösung: Verwende null für absichtlich fehlende Werte, die in der serialisierten Ausgabe erscheinen müssen. Reserviere undefined nur für Felder, die aus dem JSON ausgeschlossen werden sollen.
const userProfile = {
userId: "usr_4421",
displayName: "Lukas Bauer",
avatarUrl: undefined, // verschwindet stillschweigend
bio: undefined // verschwindet stillschweigend
}
JSON.stringify(userProfile, null, 2)
// { "userId": "usr_4421", "displayName": "Lukas Bauer" }
// avatarUrl und bio sind weg — keine Warnungconst userProfile = {
userId: "usr_4421",
displayName: "Lukas Bauer",
avatarUrl: null, // explizit abwesend — erscheint in der Ausgabe
bio: null // explizit abwesend — erscheint in der Ausgabe
}
JSON.stringify(userProfile, null, 2)
// {
// "userId": "usr_4421",
// "displayName": "Lukas Bauer",
// "avatarUrl": null,
// "bio": null
// }Problem: Ein BigInt-Wert an JSON.stringify() zu übergeben, wirft zur Laufzeit einen TypeError. Das ist ein harter Absturz, keine stille Auslassung — er tritt in der Produktion auf, wenn ein numerisches Feld Number.MAX_SAFE_INTEGER überschreitet.
Lösung: Verwende eine Replacer-Funktion, die BigInt-Werte vor der Serialisierung in Strings konvertiert. Alternativ kann BigInt vor der Übergabe an JSON.stringify in String oder Number umgewandelt werden.
const session = {
sessionId: 9007199254741234n, // BigInt-Literal
userId: "usr_4421",
startedAt: "2026-03-10T14:00:00Z"
}
JSON.stringify(session, null, 2)
// Uncaught TypeError: Do not know how to serialize a BigIntfunction bigIntReplacer(_key, value) {
return typeof value === 'bigint' ? value.toString() : value
}
const session = {
sessionId: 9007199254741234n,
userId: "usr_4421",
startedAt: "2026-03-10T14:00:00Z"
}
JSON.stringify(session, bigIntReplacer, 2)
// {
// "sessionId": "9007199254741234",
// "userId": "usr_4421",
// "startedAt": "2026-03-10T14:00:00Z"
// }Problem: Objekte, die auf sich selbst verweisen — häufig in DOM-Bäumen, verketteten Listen und manchen ORM-Ergebnismengen — werfen einen TypeError, wenn sie an JSON.stringify() übergeben werden. Der Fehler tritt erst zur Serialisierungszeit auf, oft weit entfernt von der Stelle, an der die zirkuläre Referenz erstellt wurde.
Lösung: Verwende eine Replacer-Funktion mit einem WeakSet, um zirkuläre Referenzen zu erkennen und zu ersetzen, oder installiere die flatted-Bibliothek als Drop-in-Ersatz, der zirkuläre Strukturen nativ behandelt.
const dept = { id: "dept_eng", name: "Engineering" }
const team = { id: "team_frontend", dept }
dept.teams = [team] // zirkulär: dept → team → dept
JSON.stringify(dept, null, 2)
// Uncaught TypeError: Converting circular structure to JSONimport { stringify } from 'flatted' // npm install flatted
const dept = { id: "dept_eng", name: "Engineering" }
const team = { id: "team_frontend", dept }
dept.teams = [team]
// flatted behandelt zirkuläre Refs — Hinweis: Ausgabe ist flatted-Format, kein Standard-JSON
stringify(dept)
// Oder WeakSet-basierten Replacer verwenden für Standard-JSON-Ausgabe:
function circularReplacer() {
const seen = new WeakSet()
return (_key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]'
seen.add(value)
}
return value
}
}
JSON.stringify(dept, circularReplacer(), 2)Problem: Ein space-Wert größer als 10 an JSON.stringify() zu übergeben, wirft keinen Fehler — der Wert wird stillschweigend auf 10 begrenzt. Entwickler, die 20 Leerzeichen pro Einrückung für tiefe Verschachtelung erwarten, erhalten nur 10, was zu unerwarteter Formatierung in generierten Dateien führt.
Lösung: Die maximale Einrückung beträgt 10 Leerzeichen. Für tiefe Strukturen bevorzuge 2-Leerzeichen-Einrückung (die häufigste Konvention in JavaScript-Projekten) und verlass dich auf einklappbare Editoren für die Navigation.
const deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }
// 20-Leerzeichen-Einrückung erwartet — aber space wird auf 10 begrenzt
JSON.stringify(deepConfig, null, 20)
// Gleiche Ausgabe wie JSON.stringify(deepConfig, null, 10)
// Kein Fehler, keine Warnung — stillschweigend abgeschnittenconst deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }
// 2 (die meisten Projekte) oder 4 Leerzeichen verwenden — niemals 10 überschreiten
JSON.stringify(deepConfig, null, 2)
// {
// "server": {
// "tls": {
// "certs": {
// "primary": "/etc/ssl/api.pem"
// }
// }
// }
// }JSON.stringify vs. Alternativen — Schnellvergleich
Verschiedene Situationen erfordern verschiedene Tools. JSON.stringify mit einem Replacer deckt die meisten Produktionsanwendungsfälle ohne Abhängigkeiten ab. util.inspect ist die richtige Wahl für schnelles Terminal-Debugging, wenn du farbige Ausgaben brauchst und kein gültiges JSON benötigst. fast-json-stringify lohnt sich in hochdurchsatzfähigen Routen, wo Profiling Serialisierungskosten zeigt; für alles andere ist der Overhead der Schema-Pflege es nicht wert.
Häufig gestellte Fragen
Wie formatiere ich JSON in JavaScript?
Rufe JSON.stringify(data, null, 2) auf — das dritte Argument steuert die Einrückung. Übergib 2 oder 4 für Leerzeichen oder "\t" für Tabs. Kein Import oder keine Installation erforderlich: JSON ist ein globales Objekt in jeder JavaScript-Umgebung, einschließlich Browser und Node.js.
const config = { host: "api.payments.internal", port: 8443, tls: true }
console.log(JSON.stringify(config, null, 2))
// {
// "host": "api.payments.internal",
// "port": 8443,
// "tls": true
// }Was bewirkt der `space`-Parameter in JSON.stringify()?
Der space-Parameter steuert die Einrückung in der Ausgabe. Übergib eine Zahl (1–10) für diese Anzahl von Leerzeichen pro Ebene oder einen String wie "\t" für ein Tab-Zeichen. Werte über 10 werden stillschweigend auf 10 begrenzt. null, 0 oder das Weglassen des Parameters erzeugt kompaktes einzeiliges JSON.
const data = { service: "payments", version: 3, active: true }
JSON.stringify(data, null, 2) // 2 Leerzeichen Einrückung
JSON.stringify(data, null, 4) // 4 Leerzeichen Einrückung
JSON.stringify(data, null, '\t') // Tab-Einrückung
JSON.stringify(data) // kompakt: {"service":"payments","version":3,"active":true}Warum gibt JSON.stringify() für manche Werte undefined zurück?
JSON.stringify lässt Objekteigenschaften stillschweigend aus, deren Werte undefined, Funktionen oder Symbols sind — diese Typen haben keine JSON-Darstellung. Ist der oberste Wert selbst undefined, gibt die Funktion undefined zurück (nicht den String "undefined"). Verwende null statt undefined für optionale Felder, die in der Ausgabe erscheinen müssen.
const event = {
traceId: "tr_9a2f",
handler: () => {}, // Funktion — wird ausgelassen
requestId: undefined, // undefined — wird ausgelassen
sessionId: Symbol("s"), // Symbol — wird ausgelassen
status: "ok"
}
JSON.stringify(event, null, 2)
// { "traceId": "tr_9a2f", "status": "ok" }Wie gehe ich mit Date-Objekten beim JSON-Formatieren um?
Date-Objekte haben eine eingebaute toJSON()-Methode, die einen ISO 8601-String zurückgibt, sodass JSON.stringify sie automatisch verarbeitet. Du brauchst keinen benutzerdefinierten Replacer für Datumsangaben — der serialisierte Wert ist ein String wie "2026-03-10T14:22:00.000Z".
const order = {
orderId: "ord_8f2a91bc",
placedAt: new Date("2026-03-10T14:22:00Z"),
total: 42.98
}
JSON.stringify(order, null, 2)
// {
// "orderId": "ord_8f2a91bc",
// "placedAt": "2026-03-10T14:22:00.000Z",
// "total": 42.98
// }Wie formatiere ich einen JSON-String (kein Objekt) in JavaScript?
Parse den String zuerst mit JSON.parse(), dann serialisiere ihn erneut mit JSON.stringify(). Die beiden Aufrufe können für schnelles Debugging in einer Zeile verkettet werden.
const raw = '{"endpoint":"/api/v2/users","timeout":30,"retry":true}'
const formatted = JSON.stringify(JSON.parse(raw), null, 2)
console.log(formatted)
// {
// "endpoint": "/api/v2/users",
// "timeout": 30,
// "retry": true
// }Kann ich JSON.stringify() im Browser verwenden?
Ja. JSON ist ein eingebautes Global in jedem modernen Browser seit IE8 — keine Script-Tags oder Imports nötig. Öffne die DevTools-Konsole und rufe JSON.stringify() direkt auf. Es funktioniert identisch zur Node.js-Version, mit der gleichen Parameter-Signatur und den gleichen Einschränkungen bei BigInt und zirkulären Referenzen.
// Funktioniert in Chrome, Firefox, Safari, Edge — keine Imports nötig
const payload = { userId: "usr_7b3c", action: "checkout", cart: ["SKU-001", "SKU-002"] }
copy(JSON.stringify(payload, null, 2)) // copy() ist ein DevTools-HelferJavaScript gibt dir volle Kontrolle — Replacer-Funktionen, eigenes toJSON(), Verarbeitung großer Dateien in Node.js. Wenn du nur einen formatierten Ausschnitt prüfen oder teilen möchtest, ist der JSON Formatter von ToolDeck der schnellste Weg: JSON einfügen und ein formatiertes, hervorgehobenes Ergebnis ohne jedes Environment-Setup erhalten.
Verwandte Tools
Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.