Zum Inhalt springen
Toova
Alle Werkzeuge

JSON in JavaScript formatieren — 5 Methoden

Toova

JSON ist überall: API-Antworten, Konfigurationsdateien, Datenbank-Exporte, Log-Pipelines. Aber rohe JSON-Ausgaben sind oft ein kompakter Blob — keine Zeilenumbrüche, keine Einrückung, Schlüssel in der Reihenfolge, in der sie der Serialisierer ausspuckt. Das macht das Debuggen mühsam und die Zusammenarbeit unnötig schwierig.

JavaScript bietet Ihnen mehrere Möglichkeiten, JSON zu formatieren — vom eingebauten JSON.stringify bis zu Streaming-Bibliotheken für Dateien, die zu groß sind, um in den Speicher geladen zu werden. Dieser Leitfaden behandelt fünf praktische Methoden, die häufigsten Fälle und die Sonderfälle, über die Entwickler stolpern.

Methode 1: JSON.stringify mit Einrückung

Der einfachste Ansatz ist bereits in die Sprache eingebaut. JSON.stringify akzeptiert drei Argumente: den zu serialisierenden Wert, einen Replacer (mehr dazu in Methode 2) und einen space-Parameter, der die Einrückung steuert.

const data = {
  name: "Alice",
  role: "engineer",
  skills: ["JavaScript", "TypeScript", "Node.js"],
  active: true,
};

// 2-space indent (common default)
console.log(JSON.stringify(data, null, 2));

// 4-space indent
console.log(JSON.stringify(data, null, 4));

// Tab indent
console.log(JSON.stringify(data, null, "\t"));

Mit null, 2 sieht die Ausgabe so aus:

{
  "name": "Alice",
  "role": "engineer",
  "skills": [
    "JavaScript",
    "TypeScript",
    "Node.js"
  ],
  "active": true
}

Zwei Leerzeichen sind die häufigste Konvention in JavaScript-Projekten — sie entspricht dem Standard in ESLint, Prettier und den meisten Style Guides. Vier Leerzeichen sind in Python-nahem Tooling verbreitet. Wenn space weggelassen oder auf 0 gesetzt wird, ist die Ausgabe ein kompakter einzeiliger String — ideal für die Übertragung über Netzwerke.

Sie können JSON auch sofort im Browser mit dem JSON Formatter-Tool formatieren — fügen Sie rohes JSON ein, erhalten Sie schön formatierte Ausgabe und kopieren Sie das Ergebnis ohne Code zu schreiben.

Methode 2: Benutzerdefinierte Replacer-Funktion

Das zweite Argument von JSON.stringify — der Replacer — ist eine Funktion oder ein Array, das Werte vor der Serialisierung filtert und transformiert. Hier erhalten Sie echte Kontrolle darüber, was in der Ausgabe landet.

Die Array-Form ist der einfachste Ansatz für Key-Whitelisting:

const user = {
  id: 42,
  name: "Bob",
  password: "s3cr3t",
  email: "bob@example.com",
  createdAt: new Date(),
};

// Array replacer: include only listed keys
const safeJson = JSON.stringify(user, ["id", "name", "email"], 2);
console.log(safeJson);
// {
//   "id": 42,
//   "name": "Bob",
//   "email": "bob@example.com"
// }

Die Funktionsform gibt Ihnen Kontrolle über jeden einzelnen Wert. Geben Sie den Wert zurück, um ihn einzuschließen, geben Sie undefined zurück, um ihn wegzulassen, oder geben Sie einen transformierten Wert zurück:

function replacer(key, value) {
  // Drop keys that start with underscore (private convention)
  if (key.startsWith("_")) return undefined;

  // Mask sensitive fields
  if (key === "password" || key === "token") return "[REDACTED]";

  // Convert Date objects to ISO strings explicitly
  if (value instanceof Date) return value.toISOString();

  return value;
}

const payload = {
  id: 1,
  name: "Carol",
  password: "hunter2",
  _internalFlag: true,
  lastLogin: new Date("2026-05-01"),
};

console.log(JSON.stringify(payload, replacer, 2));
// {
//   "id": 1,
//   "name": "Carol",
//   "password": "[REDACTED]",
//   "lastLogin": "2026-05-01T00:00:00.000Z"
// }

Der Replacer wird rekursiv auf jedes verschachtelte Objekt und Array angewendet. Dieses Muster ist nützlich für Logging-Pipelines, bei denen Sie Zugangsdaten entfernen möchten, bevor Sie auf Disk schreiben oder an einen Observability-Service senden.

Methode 3: Schön formatieren mit sortierten Schlüsseln

JavaScript-Objekte garantieren keine Schlüsselreihenfolge (obwohl V8 und die meisten Engines die Einfügereihenfolge für String-Schlüssel beibehalten). Wenn Sie deterministische Ausgabe benötigen — zum Diffing, Caching oder für kanonische Darstellungen — ist das alphabetische Sortieren von Schlüsseln der richtige Ansatz.

function sortedStringify(value, indent = 2) {
  return JSON.stringify(value, sortReplacer, indent);
}

function sortReplacer(key, value) {
  if (value !== null && typeof value === "object" && !Array.isArray(value)) {
    return Object.keys(value)
      .sort()
      .reduce((sorted, k) => {
        sorted[k] = value[k];
        return sorted;
      }, {});
  }
  return value;
}

const config = {
  version: "1.0",
  author: "Dave",
  dependencies: { typescript: "^5.4", eslint: "^9.0", astro: "^5.0" },
  name: "my-project",
};

console.log(sortedStringify(config));
// {
//   "author": "Dave",
//   "dependencies": { "astro": "^5.0", "eslint": "^9.0", "typescript": "^5.4" },
//   "name": "my-project",
//   "version": "1.0"
// }

Sortierte Schlüssel bedeuten, dass Git-Diffs nur die tatsächlich geänderten Zeilen anzeigen, anstatt willkürliche Neuordnungen von verschiedenen Serialisierern. Das ist besonders nützlich für package.json und ähnliche Konfigurationsdateien, die in der Versionskontrolle gespeichert sind.

Für die Konvertierung von JSON in andere Formate behandeln auch das JSON zu YAML-Tool und das JSON zu CSV-Tool die Schlüsselreihenfolge in ihrer Ausgabe.

Methode 4: Aus einem String formatieren (Parse + Stringify)

JSON kommt in der Praxis meist als String — aus einer Fetch-Antwort, einem Datei-Read, einem Clipboard-Einfügen oder einer Datenbank-TEXT-Spalte. Sie müssen es erst parsen, dann neu formatieren. Das Entscheidende ist eine ordentliche Fehlerbehandlung: Ungültiges JSON wirft einen Fehler, und Sie möchten ihn elegant abfangen.

function formatJsonString(rawString, indent = 2) {
  try {
    const parsed = JSON.parse(rawString);
    return { ok: true, result: JSON.stringify(parsed, null, indent) };
  } catch (err) {
    return { ok: false, error: err.message };
  }
}

const raw = '{"name":"Eve","scores":[100,95,88],"active":true}';
const { ok, result, error } = formatJsonString(raw);

if (ok) {
  console.log(result);
  // {
  //   "name": "Eve",
  //   "scores": [100, 95, 88],
  //   "active": true
  // }
} else {
  console.error("Parsing failed:", error);
}

// Invalid input
const bad = '{"name": "Eve", "broken":}';
const r2 = formatJsonString(bad);
// { ok: false, error: "Unexpected token '}'" }

Das Einwickeln von Parse-Fehlern in ein strukturiertes Return-Objekt macht diese Funktion sicher für die Verwendung in UI-Komponenten und Build-Skripten, ohne jede Aufrufstelle in ein try/catch zu hüllen. Die MDN-Dokumentation für JSON.stringify deckt die vollständige Parameterspezifikation ab, und RFC 8259 definiert, wie gültiges JSON auf Protokollebene aussieht.

Methode 5: Streaming für große Dateien

Die Methoden 1–4 laden die gesamte JSON-Struktur in den Speicher, bevor sie formatiert wird. Für Dateien im Bereich von hunderten Megabytes oder mehreren Gigabytes blockiert das den Node.js-Event-Loop und kann den Prozess zum Absturz bringen.

Der Streaming-Ansatz liest die Datei in Chunks und schreibt formatierte Ausgabe schrittweise. Für NDJSON (ein JSON-Objekt pro Zeile, verbreitet in Log-Dateien und Datenbank-Exporten) funktioniert ein readline-basierter Ansatz ohne zusätzliche Abhängigkeiten:

import { createReadStream, createWriteStream } from "node:fs";
import { createInterface } from "node:readline";

async function formatNdjsonFile(inputPath, outputPath) {
  const rl = createInterface({
    input: createReadStream(inputPath),
    crlfDelay: Infinity,
  });

  const output = createWriteStream(outputPath);

  for await (const line of rl) {
    if (!line.trim()) continue;
    try {
      const obj = JSON.parse(line);
      output.write(JSON.stringify(obj, null, 2) + "\n---\n");
    } catch (e) {
      output.write("[Invalid JSON line: " + e.message + "]\n---\n");
    }
  }

  output.end();
}

NDJSON ist das einfachste Streaming-Format: jede Zeile ist ein gültiges, vollständiges JSON-Objekt. Viele Export-Tools unterstützen es genau deshalb, weil es trivial streambar ist. Wenn Sie das Format großer Datenexporte kontrollieren, bevorzugen Sie NDJSON gegenüber einem einzigen riesigen JSON-Array.

Sonderfälle, auf die Sie achten sollten

Das sind die Szenarien, in denen die Standard-JSON-Formatierung entweder stillschweigend versagt oder unerwartet eine Ausnahme wirft.

Zirkuläre Referenzen

JSON.stringify wirft einen TypeError, wenn ein Objekt direkt oder indirekt auf sich selbst verweist. Beheben Sie das mit einem Replacer, der besuchte Objekte mit einem WeakSet verfolgt:

function safeStringify(obj, indent = 2) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) return "[Circular]";
      seen.add(value);
    }
    return value;
  }, indent);
}

const a = { name: "circular" };
a.self = a;
console.log(safeStringify(a));
// { "name": "circular", "self": "[Circular]" }

Das WeakSet hält Referenzen, ohne deren Garbage-Collection zu verhindern, was Speicherlecks in langlebigen Prozessen vermeidet.

BigInt-Werte

JSON.stringify wirft einen TypeError für BigInt-Werte, weil die JSON-Spezifikation keinen 64-Bit-Ganzzahltyp hat. Konvertieren Sie in Ihrem Replacer zu String:

const data = { id: 9007199254740993n, value: 42 };

JSON.stringify(data, (key, value) =>
  typeof value === "bigint" ? value.toString() : value
, 2);
// { "id": "9007199254740993", "value": 42 }

Map- und Set-Werte

Map wird als leeres Objekt und Set als leeres Array serialisiert — nicht deren Inhalte. Konvertieren Sie sie explizit in einem Replacer:

const data = {
  tags: new Set(["json", "javascript"]),
  meta: new Map([["source", "api"]]),
};

JSON.stringify(data, (key, value) => {
  if (value instanceof Set) return [...value];
  if (value instanceof Map) return Object.fromEntries(value);
  return value;
}, 2);
// { "tags": ["json", "javascript"], "meta": { "source": "api" } }

undefined-Werte

Objekteigenschaften mit undefined-Werten werden stillschweigend weggelassen. Array-Slots mit undefined werden zu null. Verwenden Sie einen Replacer, um undefined in null zu konvertieren, wenn Sie alle Schlüssel beibehalten möchten:

const obj = { a: 1, b: undefined, c: null };
JSON.stringify(obj, null, 2);
// { "a": 1, "c": null }  — "b" is silently dropped

// Fix:
JSON.stringify(obj, (key, value) =>
  value === undefined ? null : value
, 2);
// { "a": 1, "b": null, "c": null }

JSON sofort im Browser formatieren

Wenn Sie einen JSON-Blob jetzt formatieren müssen, ohne Code zu schreiben, erledigt der Toova JSON Formatter das mit einem Klick — fügen Sie rohes JSON ein, erhalten Sie schön formatierte Ausgabe mit 2- oder 4-Leerzeichen-Einrückung und kopieren Sie das Ergebnis. Keine Registrierung, kein Datei-Upload — alles läuft lokal in Ihrem Browser.

Für Konvertierungen zwischen Formaten folgen JSON zu YAML und JSON zu CSV demselben datenschutzorientierten Ansatz — Ihre Daten verlassen nie Ihr Gerät.

Fazit

Für die meisten Anwendungsfälle reicht JSON.stringify(obj, null, 2) aus. Fügen Sie eine Replacer-Funktion hinzu, wenn Sie Filterung, Maskierung oder sortierte Schlüssel benötigen. Wickeln Sie JSON.parse in ein try/catch, wenn Sie externe Eingaben verarbeiten. Verwenden Sie Streaming nur, wenn die Dateigröße das synchrone Parsen unpraktikabel macht. Und behalten Sie die Sonderfälle — zirkuläre Referenzen, BigInt, Map/Set, undefined — im Hinterkopf, wenn Sie mit ungewöhnlichen Datenstrukturen arbeiten.