JSON-Vergleich

Vergleichen Sie zwei JSON-Objekte und sehen Sie die Unterschiede hervorgehoben.

Keine Daten verlassen Ihr Gerät

Über den JSON-Vergleich

Der JSON-Vergleich (auch JSON-Diff genannt) identifiziert die Unterschiede zwischen zwei JSON-Strukturen. Anders als ein einfacher Text-Diff versteht ein JSON-bewusster Vergleich Schlüssel und Werte, sodass er Ihnen genau sagen kann, welche Eigenschaften hinzugefügt, entfernt oder geändert wurden, unabhängig von der Schlüssel-Reihenfolge.

Dieses Tool führt einen tiefen, rekursiven Vergleich von zwei JSON-Objekten durch. Es behandelt verschachtelte Objekte, Arrays, Strings, Zahlen, Booleans und Null-Werte. Die gesamte Verarbeitung findet lokal in Ihrem Browser statt.

Eine kurze Geschichte von JSON

JSONs Biografie ist kürzer als die der durchschnittlichen Programmiersprache und deutlich weniger dramatisch. Das Akronym entstand bei State Software, Inc., einer kleinen Firma, die Douglas Crockford und Chip Morningstar im März 2001 gegründeten, um das zu bauen, was später Ajax-Webanwendungen genannt würde. Die erste JSON-Nachricht wurde im April 2001 von einem Computer in Morningstars Garage in der Bay-Area gesendet. Crockford behauptet nicht, JSON erfunden zu haben, er löste es aus der JavaScript-Objekt-Literal-Syntax heraus, gab ihm einen Namen und stellte eine Website auf. Er erwarb json.org 2002 und stellte dort eine Grammatik in Eisenbahndiagramm-Form ein. Vier Jahre lang verbreitete sich JSON durch Mundpropaganda und ein langsames Tröpfeln von Bibliotheksimplementierungen. Im Dezember 2005 begann Yahoo!, einige seiner Webdienste in JSON anzubieten, der Moment, den die meisten Historiker als JSONs Eintritt in den Mainstream nennen. Standardisierung kam in Wellen: RFC 4627 (Juli 2006), von Crockford selbst verfasst, mit informationellem statt Standards-Track-Status; ECMA-404 erste Ausgabe (Oktober 2013); RFC 7159 (März 2014), die JSON in den IETF Standards Track stellte und die Anforderung lockerte, dass der Top-Level-Wert ein Objekt oder Array sein muss. Die aktuellen Versionen sind RFC 8259 (Dezember 2017), jetzt Internet Standard STD 90, und ECMA-404 zweite Ausgabe (Dezember 2017). Beide sind in der Grammatik bewusst identisch; der IETF-Text fügt Sicherheits- und Interoperabilitätsleitlinien hinzu, die der Ecma-Text bewusst auslässt.

Zwei algorithmische Familien: Zeilen-Diff und struktureller Diff

Die Informatik denkt seit den 1970er Jahren über Diffs nach. Douglas McIlroy (derselbe McIlroy, der die Unix-Pipes erfand) und James W. Hunt schrieben das ursprüngliche Unix-diff Anfang der 1970er; es wurde Teil der 5. Edition von Unix 1974, mit dem zugrundeliegenden Algorithmus dokumentiert im Bell Labs Computing Science Technical Report #41 im Juni 1976. Hunt-McIlroy basiert auf dem Problem der längsten gemeinsamen Teilfolge: finde die längste Folge von Zeilen, die in beiden Eingaben in dieser Reihenfolge auftritt, und alles, was nicht in dieser Folge ist, ist entweder eine Löschung oder eine Einfügung. Ein Jahrzehnt später veröffentlichte Eugene W. Myers „An O(ND) Difference Algorithm and Its Variations" in Algorithmica Vol 1, Issue 2 (1986) und reformulierte das Problem als Kürzeste-Wege-Suche über einem „Edit-Graph", die Grundlage einer schnelleren Unix-diff-Implementierung, die zwei- bis viermal schneller lief als ihr Vorgänger. Heute verwendet git diff standardmäßig einen Histogramm-Algorithmus in LibXDiff, in der Regel schneller als reines Myers und produziert lesbarere Ausgaben, besonders um verschobene Blöcke herum. Patience Diff (Bram Cohen, 2008) ist eine weitere LCS-Verfeinerung, die einzigartige Ankerzeilen priorisiert. Alle Variationen eines Themas: zeilenweise LCS, die Eingabe als flache Folge opaker Tokens behandelnd. Keiner weiß, was JSON ist.

Die strukturelle Diff-Familie wählt einen anderen Ansatz: beide Eingaben parallel durchlaufen, Primitive mit strenger Gleichheit vergleichen, die Vereinigung der Objekt-Schlüssel berechnen (nur-links-vorhanden ist „entfernt", nur-rechts-vorhanden ist „hinzugefügt", in-beiden-vorhanden bedeutet Rekursion) und Arrays nach Index durchlaufen. Für jede Position Rekursion. Wenn ein Array länger ist, sind die zusätzlichen Elemente hinzugefügt oder entfernt. Typänderungen (Zahl vs String, Objekt vs Array) werden zu „Typ geändert"-Einträgen. Das ist der Algorithmus, den jsondiffpatch als Basisfall implementiert, und das ist der Algorithmus, den dieses Tool implementiert. Seine Stärke ist, dass die Ausgabe bedeutungsvoll ist: jede gemeldete Änderung hat einen Pfad im Dokument (user.address.city, items[3].price) und klare Semantik. Seine Schwäche ist der dritte Schritt, der Array-Vergleich nach Index, der Unsinn produziert, sobald ein Element nahe dem Anfang eines langen Arrays eingefügt wird.

Das härteste Problem beim JSON-Diff: Arrays

Angenommen, Ihr „vorher"-JSON enthält das Array ["alpha", "beta", "gamma", "delta"] und Ihr „nachher"-JSON enthält ["alpha", "new", "beta", "gamma", "delta"]. Ein naiver indexbasierter Diff meldet vier Änderungen: Index 1 wechselte von „beta" zu „new"; Index 2 wechselte von „gamma" zu „beta"; Index 3 wechselte von „delta" zu „gamma"; Index 4 fügte „delta" hinzu. Ein Mensch, der das ansieht, würde sagen, es gibt eine Änderung: eine einzelne Einfügung an Index 1. Das ist dasselbe LCS-Problem, das die Zeilen-Diff-Familie in den 1970ern gelöst hat, angewandt auf Arrays von JSON-Werten statt auf Arrays von Textzeilen. jsondiffpatch tut genau das, berechnet das LCS der beiden Arrays und gibt Einfügungen und Löschungen relativ dazu aus. Bei Arrays von Primitiven funktioniert das gut. Bei Arrays von Objekten nicht: [{id: 1, name: "Alice"}] versus [{id: 1, name: "Alicia"}] haben keine gemeinsame Teilfolge nach Referenzgleichheit, also meldet naives LCS „das ganze linke Element löschen, das ganze rechte Element hinzufügen", wenn die Wahrheit ist, dass ein Feld eines Elements sich änderte. jsondiffpatchs Lösung ist der objectHash-Callback: der Aufrufer liefert eine Funktion, die jedes Objekt auf einen Identitätsschlüssel abbildet (typischerweise obj => obj.id), und der Diff matcht Array-Elemente nach Identität statt nach Referenz. Das ist ein schwieriges allgemeines Problem, das niemand vollständig gelöst hat. Das Absolutool-Tool, laut seinem eigenen FAQ, vergleicht Arrays nach Index, es implementiert weder LCS noch objectHash. Das ist eine bewusste Scope-Entscheidung für ein kleines kostenloses Tool: es ist hervorragend bei Objekt-Diffs und schwächer bei Arrays, in denen Elemente eingefügt oder umsortiert wurden.

JSON Patch (RFC 6902): Diffs als Transportformat

RFC 6902, „JavaScript Object Notation (JSON) Patch", wurde im April 2013 veröffentlicht. Sie definiert den Medientyp application/json-patch+json und eine Sechs-Operationen-Patch-Sprache: add, remove, replace, move, copy, test. Ein Patch ist selbst ein JSON-Dokument, ein Array von Operations-Objekten, jedes mit einem op-Schlüssel, einem path-Schlüssel (ein JSON Pointer auf die Zielposition) und einem Wert- oder from-Feld je nach Bedarf. Operationen werden in Reihenfolge angewandt, atomar: wenn eine fehlschlägt, wird der ganze Patch abgelehnt. Die Pfad-Syntax kommt von RFC 6901, „JSON Pointer", einem Begleitdokument, im selben Monat veröffentlicht, einer winzigen String-Syntax aus slash-getrennten Referenz-Tokens (/user/address/city bedeutet „der Wert bei Schlüssel city innerhalb von address innerhalb von user"; /items/3 bedeutet „das vierte Element von items", null-indiziert). Weil / und ~ speziell sind, werden sie zu ~1 bzw. ~0 escapet (in dieser Reihenfolge, ~1 zuerst dekodieren, um Doppel-Dekodier-Bugs zu vermeiden). JSON Patch ist das richtige Ausgabeformat für ein JSON-Diff-Tool, das das Ergebnis an eine andere Maschine geben will. Die HTTP-PATCH-Methode (RFC 5789) wurde genau für diese Art Teil-Update-Payload entworfen. Kubernetes unterstützt RFC 6902 neben seinem eigenen Strategic-Merge-Patch-Format. Dieses Tool emittiert derzeit kein JSON Patch, das ist eine zukünftige Funktionsrichtung, keine aktuelle.

JSON Merge Patch (RFC 7396): die einfachere, verlustbehaftete Alternative

RFC 7396, „JSON Merge Patch", wurde im Oktober 2014 von Paul Hoffman und James Snell veröffentlicht. Sie verwendet überhaupt keine Operationen, das Patch-Dokument ist einfach ein partielles JSON-Objekt, das auf das Original gelegt wird. Jedes im Patch vorhandene Feld überschreibt das entsprechende Feld im Original; jedes im Patch auf null gesetzte Feld entfernt dieses Feld; jedes im Patch nicht vorhandene Feld bleibt unverändert; Arrays werden als Ganzes ersetzt, nie zusammengeführt. Merge Patch ist prägnant und leicht von Hand zu schreiben. Der Kompromiss ist der Verlust an Ausdrucksstärke: keine Möglichkeit, einen Feldwert auf wörtliches null zu setzen (weil null „löschen" bedeutet); keine Möglichkeit, ein einzelnes Array-Element zu modifizieren (das ganze Array wird ersetzt); keine Möglichkeit, ein Move oder Copy auszudrücken; keine Möglichkeit, „ich habe dieses Feld nicht angefasst" von „ich will es auf seinen aktuellen Wert setzen" zu unterscheiden. Für die meisten alltäglichen API-Updates sind diese Einschränkungen akzeptabel, weshalb Merge Patch das beliebtere der beiden Formate ist. RFC 6902 gewinnt in Szenarien, in denen eine der Einschränkungen beißt. Kubernetes verwendet bewusst beide Formate und wählt das richtige für den jeweiligen Kontext.

Wie der visuelle Diff gerendert wird

Es gibt drei verbreitete visuelle Konventionen für die Darstellung eines strukturellen Diffs. Seite-an-Seite, zwei Spalten, Original links, Modifiziert rechts, mit korrespondierenden Zeilen ausgerichtet (das Layout, das dieses Tool für seine Eingaben verwendet). Inline-Unified-Diff, eine einzelne Spalte, die entfernte Zeilen zeigt (typischerweise mit - präfixiert und rot gefärbt), hinzugefügte Zeilen (+, grün) und unveränderte Kontextzeilen (kein Präfix, schlichter Text), das Layout, das git diff standardmäßig verwendet. Baumansicht, das JSON als einklappbaren Baum rendern, mit hervorgehobenen geänderten Knoten und eingeklappten unveränderten Knoten. Farbkonventionen sind im Ökosystem bemerkenswert konsistent: Grün für Ergänzungen, Rot für Entfernungen, Gelb oder Bernstein für geänderte Werte, neutrales Grau für unveränderte. Dieses Tool folgt der Konvention exakt: hellgrün für Ergänzungen, hellrot für Entfernungen, hellgelb für Änderungen. Die meisten Benutzer werden die Farben von GitHub, GitLab, BitBucket, jeder IDE-Diff-Ansicht und Dutzenden von Online-Tools wiedererkennen.

Häufige Anwendungsfälle

Beachtenswerte Grenzfälle

Zahlenpräzision. RFC 8259 sagt, JSON-Zahlen sind beliebig präzise und setzt keine Obergrenze für die Anzahl der Stellen. JavaScript parst jedoch jede Zahl als 64-Bit-IEEE-754-Double. Oberhalb von Number.MAX_SAFE_INTEGER (253 − 1 = 9.007.199.254.740.991) können Ganzzahlen beim Round-Trip durch einen JavaScript-basierten Diff stillschweigend Präzision verlieren. Dasselbe Problem betrifft Gleitkomma, 0.1 + 0.2 ist bekanntermaßen nicht exakt 0.3 in IEEE 754. Striktes JSON verbietet auch nachgestellte Kommata und Kommentare; beides sind Syntaxfehler nach RFC 8259. JSON5 (json5.org) ist eine formelle Übermenge, die Kommentare, nachgestellte Kommata, einfache Anführungszeichen, ungequotete Schlüssel, Hex-Zahlen, führende/nachgestellte Dezimalpunkte und Infinity/NaN erlaubt. JSONC ist Microsofts „JSON with Comments"-Modus, verwendet in VS Codes Einstellungsdateien. Dieses Tool verwendet JSON.parse() und wird daher beide ablehnen, entfernen Sie Kommentare und nachgestellte Kommata vor dem Einfügen.

Datums-Strings. JSON hat keinen nativen Datumstyp. Daten werden typischerweise als Strings kodiert, mit dem De-facto-Standard ISO 8601 (und speziell dem RFC 3339-Profil, das die meisten Internet-APIs verwenden): YYYY-MM-DDTHH:MM:SS[.fff]Z. Ein Diff, der Daten als Strings vergleicht, meldet 2024-01-01T00:00:00Z und 2024-01-01T00:00:00.000Z als unterschiedlich, obwohl sie denselben Moment repräsentieren, weil die Strings sich unterscheiden. Doppelte Schlüssel. RFC 8259 §4 stellt fest: „Namen innerhalb eines Objekts SOLLTEN eindeutig sein", das SOLLTEN ist normativ schwächer als MÜSSEN. JavaScripts JSON.parse() akzeptiert doppelte Schlüssel und behält stillschweigend den letzten; andere Parser behalten den ersten oder lösen einen Fehler aus. null vs fehlend. {"a": null} und {} sind unterschiedliche JSON-Werte. Dieses Tool meldet ersteres als „Schlüssel a hat Wert null" und zweites als „kein Schlüssel a", sie werden korrekt unterschieden. Die Behandlung von null als Lösch-Signal durch JSON Merge Patch ist ein Eingeständnis auf Format-Ebene, dass die Unterscheidung real und heikel ist.

Das Ökosystem 2026

Open-Source-JSON-Diff wird von einer Handvoll Bibliotheken dominiert. jsondiffpatch von Benjamin Eidelman, erstmals 2012 veröffentlicht, ist die De-facto-JavaScript-Bibliothek: ~5k GitHub-Sterne, unterstützt objectHash, LCS-Arrays, Reverse-Patches und einen visuellen HTML-Formatierer. json-diff von Andrey Tarantsov ist das kanonische Node-CLI-Tool, mit demselben Namen geteilt von parallelen Implementierungen in Python, Go und Rust. DeepDiff von Sep Dehpour ist die dominante Python-Bibliothek, rekursiver Diff mit Optionen für Ignorieren von Reihenfolge, Ignorieren von numerischen Typänderungen und einer Vielzahl feinkörniger Steuerungen. Das JsonNode-Diffing in Jackson (Java) der Linux Foundation ist die Standardwahl für die JVM. jq hat keinen nativen Diff-Befehl, aber seine Operator-Familie = und // kann einfache strukturelle Vergleiche ausdrücken. Der eingebaute Diff von VS Code behandelt JSON über Textmodus; die Erweiterung JSON Tools fügt JSON-bewussten Vergleich hinzu. Online-Tools wie Diffchecker bieten JSON-Modi, die im Wesentlichen denselben rekursiven Durchlauf darstellen, den dieses Tool implementiert, oft auf denselben Bibliotheken aufgesetzt.

Warum nur-Browser hier zählt

Zwei JSON-Payloads auf einem Server zu diffen erfordert, beide hochzuladen. Für gewöhnliche öffentliche Datenbeispiele ist das harmlos. Für API-Antworten, die Authentifizierungs-Tokens, Kunden-PII, interne Mitarbeiter-Datensätze, Konfigurations-Geheimnisse oder unveröffentlichte Produktdaten enthalten, ist es das nicht. Selbst nachdem der Diff fertig ist, sitzen diese Payloads in Server-Logs, möglicherweise in einem CDN-Cache, möglicherweise in einer Analytics-Pipeline, möglicherweise in einem Backup. Ein nur-Browser-Diff überträgt nie, das JSON wird vollständig in Ihrem Tab geparst und durchlaufen. Sie können das überprüfen, indem Sie beim Klick auf Compare den Network-Tab der DevTools öffnen; es gibt keine ausgehenden Requests. Zum Vergleich von API-Antworten gegen eine Basis, zum Debuggen von Konfigurations-Drift zwischen Umgebungen oder zum Auditieren von Änderungen in einem Lockfile mit internen Paket-URLs ist „das JSON verlässt mein Gerät nie" die Architektur, die das Tool für reale Produktionsdaten sicher zu verwenden macht.

Häufig gestellte Fragen

Beeinflusst die Schlüssel-Reihenfolge den Vergleich?

Nein. JSON-Objekte sind laut Spezifikation nicht geordnet, also werden {"a":1, "b":2} und {"b":2, "a":1} als identisch behandelt. Nur tatsächliche Wertunterschiede werden gemeldet.

Wie werden Arrays verglichen?

Arrays werden nach Index verglichen. Wenn das Array an Index 2 zwischen den beiden Eingaben unterschiedlich ist, wird genau dieser Index markiert. Hinzugefügte oder entfernte Elemente am Ende werden ebenfalls erkannt.

Was passiert mit tief verschachtelten Objekten?

Der Vergleich ist vollständig rekursiv. Verschachtelte Objekte und Arrays in beliebiger Tiefe werden Eigenschaft für Eigenschaft verglichen. Die Ausgabe zeigt den vollständigen Pfad zu jedem Unterschied (z. B. „user.address.city").

Warum sieht mein Big-Integer-Vergleich falsch aus?

JavaScript parst jede JSON-Zahl als 64-Bit-IEEE-754-Double. Oberhalb von Number.MAX_SAFE_INTEGER (253 − 1 = 9.007.199.254.740.991) können Ganzzahlen stillschweigend Präzision verlieren. Also kann eine JSON-Datei, die 9007199254740993 enthält, als identisch mit einer Datei mit 9007199254740992 verglichen werden. Das ist eine Einschränkung der zugrunde liegenden Zahlendarstellung, nicht des Diff-Tools. Wenn Sie Daten mit 64-Bit-IDs (Twitter-Snowflake-IDs, Discord-IDs, große Datenbankschlüssel) diffen, lassen Sie Ihren Serialisierer sie als Strings statt als Zahlen emittieren. Gleitkomma-Vergleich hat dieselbe Einschränkung: 0.1 + 0.2 ist bekanntermaßen nicht exakt 0.3 in IEEE 754.

Kann ich JSON5 oder JSONC (JSON mit Kommentaren) vergleichen?

Nicht direkt. Dieses Tool verwendet das eingebaute JSON.parse() des Browsers, das streng RFC 8259 folgt, Kommentare, nachgestellte Kommata, einfach-gequotete Strings und ungequotete Schlüssel sind Syntaxfehler. Wenn Ihre Eingabe JSON5 (json5.org) oder VS-Code-Stil-JSONC ist, entfernen Sie zuerst die Kommentare und nachgestellten Kommata oder lassen Sie es durch ein Tool wie jsonc-parser laufen, um vor dem Einfügen in striktes JSON zu konvertieren.

Wird mein JSON an einen Server gesendet?

Nein. Der Vergleich läuft vollständig in Ihrem Browser per JavaScript. Eingefügtes JSON überquert nie das Netz, prüfen Sie im Network-Tab der DevTools beim Klick auf Compare, oder schalten Sie die Seite nach dem Laden offline und bestätigen Sie, dass der Diff weiterhin funktioniert. Sicher zum Vergleich von API-Antworten mit Auth-Tokens, Konfigurationsdateien mit Geheimnissen oder Datenbank-Exporten, die Kunden-PII enthalten.

Verwandte Tools