Wie man zwei JSON-Dateien vergleicht und Änderungen findet
Der schnellste Weg, zwei JSON-Dateien zu vergleichen, besteht darin, beide in ein nebeneinander angeordnetes Diff-Tool einzufügen, sie gleich zu formatieren und die hervorgehobenen Zeilen zu lesen. Das Schwierige ist meist nicht der Vergleich selbst. Es ist das Rauschen: umgeordnete Schlüssel, unterschiedliche Einrückung und verstreute abschließende Kommas können dazu führen, dass zwei nahezu identische Dateien aussehen, als hätten sie nichts gemeinsam.
Dieser Leitfaden erklärt, wie man einen sauberen, zuverlässigen Diff erhält. Wir schauen uns an, warum JSON-Dateien auf dem Papier auseinander driften, während sie inhaltlich gleich bleiben, die wenigen Methoden, die es wert sind zu kennen, und ein ausgearbeitetes Beispiel, dem man folgen kann. Wer einfach nur das Tool möchte, kann auf unserer JSON-Vergleichsseite all das im Browser erledigen.
Warum JSON-Dateien trügerisch schwer zu vergleichen sind
JSON hat eine kleine, strenge Grammatik (siehe die Spezifikation auf json.org), gibt Autoren aber viel Freiheit bei der Textformatierung. Zwei Dateien können dasselbe Objekt beschreiben und trotzdem Byte für Byte unterschiedlich sein. Ein einfacher Textvergleich weiß nichts davon und markiert daher alles pflichtbewusst.
Hier ist das Wichtigste, das man vor dem Start verinnerlichen sollte:
Objektschlüssel in JSON haben keine Reihenfolge. Die Spezifikation
(RFC 8259)
definiert ein Objekt als ungeordnete Menge von Name/Wert-Paaren. Also sind
{"name":"Ada","id":7} und {"id":7,"name":"Ada"}
gleich, auch wenn ein Zeilendiff sie rot und grün anzeigt.
| Was man im Diff sieht | Ist es eine echte Änderung? | Was zu tun ist |
|---|---|---|
| Schlüssel in anderer Reihenfolge | Nein, Objekte sind ungeordnet | Schlüssel auf beiden Seiten sortieren |
| 2-Leerzeichen vs. 4-Leerzeichen-Einrückung | Nein | Beide Seiten gleich formatieren |
| Minimiert vs. hübsch gedruckt | Nein | Beide Seiten formatieren |
| Abschließender Zeilenumbruch am Dateiende | Nein | Ignorieren oder Leerzeichen entfernen |
Ein Wert änderte sich von "7" zu 7 | Ja, String vs. Zahl | Untersuchen, das ist real |
| Array-Elemente in anderer Reihenfolge | Möglicherweise, Arrays sind geordnet | Entscheiden, ob die Reihenfolge hier wichtig ist |
Die letzte Zeile überrascht viele. Arrays behalten ihre Reihenfolge,
Objekte nicht. Also sind [1, 2, 3] und [3, 2, 1]
wirklich unterschiedlich, aber die Schlüssel innerhalb eines Objekts können
frei umsortiert werden. Wer die Details dazu nachlesen möchte, wie JavaScript
all das parst, findet bei MDN eine solide
Referenz zum JSON-Objekt.
Vier Methoden zum Vergleichen von JSON und wann man zu welcher greift
Es gibt keine einzige beste Methode. Es hängt davon ab, wo die Dateien liegen und was man herausfinden möchte. So schneiden die gängigen Optionen ab.
| Methode | Am besten für | Aufwand | Versteht JSON? |
|---|---|---|---|
| Manuell durchlesen | Winzige Dateien, ein oder zwei Felder | Gering | Nein, man ist der Parser |
| Online-Diff-Tool | Schnelle Prüfungen, Einfügen von überall | Gering | Mit Format + Schlüsselsortierung ja |
Befehlszeile (jq, diff) | Dateien auf der Festplatte, Scripting, große Dateien | Mittel | Ja, wenn man zuerst sortiert |
IDE oder git diff | Dateien bereits in einem Repository | Gering bei Commits | Standardmäßig zeilenbasiert |
Für die meisten Menschen gewinnt ein Browser-Tool an Geschwindigkeit, weil nichts installiert werden muss und man einen Ausschnitt direkt aus einem Protokoll oder einem API-Aufruf einfügen kann. Der Haken ist Formatierungsrauschen, das wir als nächstes behandeln. Wer viel im Terminal arbeitet, sollte jq kennenlernen, und wir zeigen das eine Flag, das wichtig ist.
Der schnellste saubere Vergleich, Schritt für Schritt
Das ist die Vorgehensweise, die ich verwende, wenn mir jemand zwei Konfigurationsdateien gibt und fragt: "Was ist anders?" Es dauert etwa fünfzehn Sekunden.
- Das JSON-Vergleichstool öffnen.
- Das Original links einfügen, die neue Version rechts.
- Auf beiden Seiten auf Formatieren klicken, damit sie die gleiche Einrückung verwenden.
- Schlüssel sortieren (kanonisieren) aktivieren, damit umgeordnete Schlüssel nicht mehr als Änderungen erscheinen.
- Das Ergebnis lesen. Grün bedeutet hinzugefügt, rot bedeutet entfernt, und ein geänderter Wert erscheint als eines von beidem.
Schritt drei und vier sind der eigentliche Trick. Sobald beide Dateien identisch formatiert und ihre Schlüssel sortiert sind, bleibt nur noch hervorgehoben, was sich tatsächlich geändert hat. Unser Diff-Engine basiert auf Googles diff-match-patch, das zuerst zeilenweise vergleicht und so auch bei langen Dateien schnell bleibt.
Ein ausgearbeitetes Beispiel
Angenommen, man prüft eine Änderung an einem Benutzerdatensatz. Hier ist der Vorher-Stand:
{
"name": "Ada Lovelace",
"role": "editor",
"active": true,
"seats": 3
}
Und hier ist der Nachher-Stand, wie ein Teammitglied ihn übergeben hat:
{
"active": true,
"name": "Ada Lovelace",
"role": "admin",
"seats": 5,
"team": "platform"
}
Wirft man diese in einen einfachen Zeilendiff, sieht es aus, als hätte sich fast jede Zeile verschoben, weil die Schlüssel in anderer Reihenfolge sind. Formatiert und sortiert man beide, ist die eigentliche Geschichte kurz:
| Feld | Vorher | Nachher | Änderung |
|---|---|---|---|
role | editor | admin | Geändert |
seats | 3 | 5 | Geändert |
team | — | platform | Hinzugefügt |
name | Ada Lovelace | Ada Lovelace | Keine Änderung |
active | true | true | Keine Änderung (nur verschoben) |
Drei echte Bearbeitungen: eine Rollenerhöhung, eine Sitzanzahl und ein
neues Team-Feld. Die Umsortierung war Rauschen. Diese Beförderung von
editor zu admin ist genau die Art von Sache,
die man im Review erkennen möchte, und sie ist leicht zu übersehen, wenn
sie unter zwanzig Zeilen falscher Positivmeldungen vergraben ist.
Formatierungsrauschen in der Befehlszeile beseitigen
Wenn die Dateien bereits auf der Festplatte liegen, funktioniert die gleiche
"Formatieren und Sortieren"-Idee mit zwei kurzen Befehlen. Das Flag
-S weist jq an, Objektschlüssel zu sortieren; das Pipen
normalisiert beide Dateien, sodass ein einfacher Diff ehrlich ist:
jq -S . old.json > old.sorted.json
jq -S . new.json > new.sorted.json
diff old.sorted.json new.sorted.json
Jetzt meldet diff nur noch Werte, die sich wirklich geändert
haben, weil beide Dateien die gleiche Einrückung und die gleiche
Schlüsselreihenfolge haben. Das ist das Terminal-Äquivalent zu Formatieren
und Schlüssel sortieren im Browser.
Textdiff vs. struktureller Diff
Alles oben Genannte ist ein Text-Diff: schnell, visuell und
perfekt für einen Menschen, der eine Änderung liest. Ein struktureller
Diff geht weiter und beschreibt die Änderung als Daten. Der Standard dafür
ist JSON Patch, definiert in
RFC 6902,
das Bearbeitungen als Operationen wie replace und
add an einem bestimmten Pfad ausdrückt. Man möchte einen
strukturellen Diff, wenn ein Programm die Änderung anwenden muss, nicht
nur eine Person, die ihn durchschaut. Für den täglichen Review ist ein
Textdiff mit sortierten Schlüsseln vollkommen ausreichend.
Häufige Fallstricke, auf die man achten sollte
| Fallstrick | Warum er zuschlägt | Lösung |
|---|---|---|
| Zahlengenauigkeit | Ganzzahlen über 2^53 − 1 verlieren Genauigkeit in JavaScript | Große IDs als Strings vergleichen; siehe MAX_SAFE_INTEGER |
| Unicode-Escapes | "café" und "café" sind derselbe String, aber unterschiedliche Bytes | Beide Seiten formatieren, was die Kodierung normalisiert |
| Doppelte Schlüssel | Die meisten Parser behalten stillschweigend den letzten | JSON validieren, bevor man dem Diff vertraut |
| Abschließende Kommas | Kein gültiges JSON; eine Datei lässt sich möglicherweise gar nicht parsen | Zuerst die Syntax reparieren, der Validator meldet es |
| String vs. Zahl | "5" und 5 sehen ähnlich aus, sind aber unterschiedliche Typen | Das ist eine echte Änderung, nicht ignorieren |
Verwandte Tools
JSON ist selten das einzige Format, mit dem man zu tun hat. Wenn man Konfigurationen zwischen Umgebungen vergleicht, wendet YAML-Vergleich dieselbe Idee auf YAML an. Änderungen zwischen zwei API-Aufrufen zu überprüfen ist genau das, wofür das API-Antwort-Diff gebaut wurde, und Abhängigkeitsaktualisierungen lassen sich am einfachsten auf der package.json diff-Seite lesen.
Häufig gestellte Fragen
- Werden JSON-Dateien beim Online-Vergleich irgendwo hochgeladen?
- Auf comparetext.org läuft der Diff im Browser. Die beiden JSON-Dateien werden von JavaScript auf dem eigenen Computer verglichen, sodass nichts an einen Server gesendet wird, es sei denn, man klickt ausdrücklich auf Speichern oder Teilen. Das macht es sicher für Konfigurationsdateien, API-Antworten und andere Daten, die man nicht auf einer beliebigen Website einfügen möchte, die bei jedem Tastendruck hochlädt.
- Warum zeigen meine zwei JSON-Dateien jede Zeile als unterschiedlich an?
- Fast immer ist es Formatierung, keine echten Änderungen. Eine Datei ist minimiert oder mit Tabulatoren eingerückt, die andere mit zwei Leerzeichen, oder die Objektschlüssel sind in anderer Reihenfolge. Auf beiden Seiten Formatieren klicken, damit sie dieselbe Einrückung verwenden, dann die Schlüssel sortieren, damit die Reihenfolge keine Rolle mehr spielt. Danach schrumpft der Diff meist auf die wenigen Werte, die sich wirklich geändert haben.
- Wie vergleiche ich JSON und ignoriere dabei die Schlüsselreihenfolge?
- JSON-Objektschlüssel haben keine definierte Reihenfolge, also sind
{"a":1,"b":2}und{"b":2,"a":1}gleich. Damit ein Textdiff zustimmt, muss man die Schlüssel auf beiden Seiten vor dem Vergleich sortieren. Im Browser die Kanonisierungs-Option (Schlüssel sortieren) verwenden. In der Befehlszeile erledigt das jq:jq -S . file.json. Sobald beide Dateien Schlüssel in derselben sortierten Reihenfolge haben, erscheinen nur noch echte Wertänderungen. - Kann ich große JSON-Dateien vergleichen, ohne dass die Seite einfriert?
- Ja, bis zu einem gewissen Punkt. Ein zeilenbasierter Diff bleibt bei Dateien mit Tausenden von Zeilen schnell, weil er zunächst ganze Zeilen vergleicht statt jedes einzelne Zeichen. Sehr große Dateien (mehrere Megabyte) lassen sich besser mit einem Befehlszeilentool wie jq oder git diff bearbeiten, das die Daten streamt. Für alles, was man bequem in einem Browser durchscrollen kann, ist ein Online-Diff die schnellere Option.
- Was ist der Unterschied zwischen einem Textdiff und einem strukturellen Diff von JSON?
- Ein Textdiff vergleicht die Dateien Zeile für Zeile, genauso wie er zwei Aufsätze vergleichen würde. Ein struktureller Diff versteht JSON, also weiß er, dass ein umgeordneter Schlüssel keine Änderung ist und dass ein in einem Array verschobener Wert eine Verschiebung ist, kein Löschen plus Hinzufügen. Textdiffs sind schneller und für die meisten Reviews ausreichend. Strukturelle Diffs (zum Beispiel JSON Patch gemäß RFC 6902) sind wichtig, wenn man eine Änderung als Daten beschreiben muss, die ein Programm anwenden kann.
- Wie vergleiche ich zwei API-Antworten?
- Jede Antwort in eine Datei speichern oder aus dem Browser-Netzwerk-Tab kopieren, dann die alte Antwort links und die neue rechts einfügen. Beide formatieren, damit die Einrückung übereinstimmt, und Schlüssel sortieren, wenn die API sie nicht in stabiler Reihenfolge zurückgibt. Das api-response-diff-Tool ist genau dafür gemacht: ein umbenanntes Feld, einen geänderten Statuscode oder einen Wert zu erkennen, der zwischen zwei Aufrufen von einem String zu einer Zahl geworden ist.
Bereit, es auszuprobieren? Dateien in das JSON-Vergleichstool einfügen und sehen, was sich geändert hat.