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.

Sieht wie eine Änderung aus, ist es meist nicht
Was man im Diff siehtIst es eine echte Änderung?Was zu tun ist
Schlüssel in anderer ReihenfolgeNein, Objekte sind ungeordnetSchlüssel auf beiden Seiten sortieren
2-Leerzeichen vs. 4-Leerzeichen-EinrückungNeinBeide Seiten gleich formatieren
Minimiert vs. hübsch gedrucktNeinBeide Seiten formatieren
Abschließender Zeilenumbruch am DateiendeNeinIgnorieren oder Leerzeichen entfernen
Ein Wert änderte sich von "7" zu 7Ja, String vs. ZahlUntersuchen, das ist real
Array-Elemente in anderer ReihenfolgeMöglicherweise, Arrays sind geordnetEntscheiden, 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.

MethodeAm besten fürAufwandVersteht JSON?
Manuell durchlesenWinzige Dateien, ein oder zwei FelderGeringNein, man ist der Parser
Online-Diff-ToolSchnelle Prüfungen, Einfügen von überallGeringMit Format + Schlüsselsortierung ja
Befehlszeile (jq, diff)Dateien auf der Festplatte, Scripting, große DateienMittelJa, wenn man zuerst sortiert
IDE oder git diffDateien bereits in einem RepositoryGering bei CommitsStandardmäß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.

  1. Das JSON-Vergleichstool öffnen.
  2. Das Original links einfügen, die neue Version rechts.
  3. Auf beiden Seiten auf Formatieren klicken, damit sie die gleiche Einrückung verwenden.
  4. Schlüssel sortieren (kanonisieren) aktivieren, damit umgeordnete Schlüssel nicht mehr als Änderungen erscheinen.
  5. 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:

Was sich tatsächlich geändert hat
FeldVorherNachherÄnderung
roleeditoradminGeändert
seats35Geändert
teamplatformHinzugefügt
nameAda LovelaceAda LovelaceKeine Änderung
activetruetrueKeine Ä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

FallstrickWarum er zuschlägtLösung
ZahlengenauigkeitGanzzahlen über 2^53 − 1 verlieren Genauigkeit in JavaScriptGroße IDs als Strings vergleichen; siehe MAX_SAFE_INTEGER
Unicode-Escapes"café" und "café" sind derselbe String, aber unterschiedliche BytesBeide Seiten formatieren, was die Kodierung normalisiert
Doppelte SchlüsselDie meisten Parser behalten stillschweigend den letztenJSON validieren, bevor man dem Diff vertraut
Abschließende KommasKein gültiges JSON; eine Datei lässt sich möglicherweise gar nicht parsenZuerst die Syntax reparieren, der Validator meldet es
String vs. Zahl"5" und 5 sehen ähnlich aus, sind aber unterschiedliche TypenDas 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.