JSON-Diff
Vergleiche zwei JSON-Dokumente und sieh, was hinzugefügt, entfernt oder geändert wurde. Schlüsselreihenfolge, Einrückung und Minifizierung zählen nicht.
JSON in beide Bereiche einfügen, um sie zu vergleichen
Die Daten vergleichen, nicht den Text
Ein zeilenweiser Vergleich beantwortet eine Frage über die Schreibweise: welche Zeilen dieser Datei keine Zeilen jener Datei sind. Für Fließtext und für Quellcode ist das die richtige Frage, für JSON die falsche, denn ein JSON-Dokument hat keine einzig richtige Schreibweise. Ordnen Sie die Mitglieder eines Objekts um, rücken Sie anders ein oder minifizieren Sie eine Seite, und jede Zeile ändert sich, während sich an den Daten überhaupt nichts bewegt. Dieses Werkzeug vergleicht, wozu die beiden Dokumente geparst werden, also ist das Gemeldete das, was sich wirklich geändert hat. Unten steht ein Dokument zweimal geschrieben — in der ersten Zeile minifiziert, danach formatiert und mit seinen Mitgliedern in einer anderen Reihenfolge.
{"name":"checkout","port":8080,"tags":["a","b"]}
{
"port": 8080,
"tags": ["a", "b"],
"name": "checkout"
}Die beiden teilen sich nicht eine einzige Zeile, und dieses Werkzeug meldet zwischen ihnen keinerlei Unterschied: dieselben Mitglieder, dieselben Werte, dieselbe Reihenfolge innerhalb der Liste. Praktisch heißt das, dass Sie nie ein Dokument neu formatieren müssen, damit ein Vergleich funktioniert — was bedeuten würde, genau das zu verändern, was Sie vergleichen wollten.
Was nie als Unterschied zählt
Vier Dinge an der Schreibweise eines Dokuments werden ignoriert, und zwar bedingungslos. Es gibt keine Einstellung, die eines davon wieder einschaltet, denn ein Werkzeug, das das könnte, wären zwei Werkzeuge mit zwei zu erklärenden Bedeutungen, und wer es liest, müsste wissen, welches der beiden die Antwort vor ihm erzeugt hat.
- Die Reihenfolge, in der die Mitglieder eines Objekts geschrieben stehen. {"a": 1, "b": 2} und {"b": 2, "a": 1} tragen dieselben Daten, also taucht ein Serialisierer, der seine Schlüssel bei jedem Lauf anders ausgibt, hier nie als Änderung auf.
- Leerraum jeder Art — die Einrückung, die Zeilenumbrüche, das Leerzeichen nach einem Doppelpunkt. Ein minifiziertes und ein formatiertes Dokument mit denselben Daten sind zweimal dasselbe Dokument.
- Wie eine Zahl geschrieben ist. 1e3 ist 1000 und 1.50 ist 1.5, denn eine JSON-Zahl hat einen Wert und keine Schreibweise: zwei Dokumente, die sich nur darin unterscheiden, tragen dieselben Zahlen, und darüber wird überhaupt nichts gemeldet.
- Wie ein Zeichen innerhalb einer Zeichenkette maskiert ist. Die sechs Zeichen \u0041 und der Buchstabe A sind dieselbe Zeichenkette aus einem Zeichen.
Zwei Dinge, die auf diese Liste zu gehören scheinen, stehen absichtlich nicht darauf. Die Reihenfolge der Elemente einer Liste ist Dateninhalt — [1, 2] und [2, 1] sind verschiedene Dokumente — und ein Mitglied mit dem Wert null ist nicht dasselbe wie ein Mitglied, das gar nicht da ist, also wird das eine gegen das andere gemeldet statt stillschweigend übergangen.
Hinzugefügt, entfernt, geändert — und ein Typwechsel
Jede Zeile des Ergebnisses gehört zu genau einer von drei Arten, und zusammen decken sie alles ab, was der Vergleich finden kann. Nehmen Sie diese beiden Dokumente:
{"host":"api.example.com","port":8080,"debug":true}
{"host":"api.example.com","port":"8080","retries":3}- Geändert bei $['port']: das Mitglied steht in beiden Dokumenten und sein Wert ist nicht derselbe, also werden beide Werte gezeigt. Dieses ist zusätzlich als Typwechsel markiert, weil 8080 eine Zahl und "8080" eine Zeichenkette ist.
- Entfernt bei $['debug']: das Mitglied steht im ersten Dokument und nicht im zweiten.
- Hinzugefügt bei $['retries']: das Mitglied steht im zweiten Dokument und nicht im ersten.
Das Mitglied namens host steht in beiden mit demselben Wert, also wird es gar nicht gemeldet. Ein Typwechsel ist eine Eigenschaft einer Änderung und keine vierte Zeilenart: er ist die Abweichung, die ein Schema bemerkt und ein Mensch, der zwei Dateien liest, meist nicht, also wird er dort benannt, wo er auftritt, statt Ihnen zum Suchen überlassen zu werden.
Wo ein Unterschied sitzt, als Pfad geschrieben
Jede Zeile benennt die Stelle, an der sie sitzt, und zwar als Pfad in das Dokument hinein und nicht als Zeilennummer — eine Zeilennummer wäre eine Aussage über die Schreibweise, also gerade über das, was dieses Werkzeug soeben ignoriert hat. Die Pfade sind normalisierte Pfade nach RFC 9535, die eine Schreibweise, die diese Website überall verwendet, wo eine Stelle in JSON festgehalten werden muss.
- $ ist das ganze Dokument, $['port'] ist das darin liegende Mitglied namens port, und $['hosts'][1] ist das Element mit Index 1 der Liste unter hosts. Ein Mitglied steht immer in eckigen Klammern und Anführungszeichen, daher braucht ein Name mit einem Punkt, einem Leerzeichen oder einer eigenen Klammer darin nichts Besonderes.
- Ein Pfad ist eine Abfrage, die Sie ausführen können. Fügen Sie ihn zusammen mit dem Dokument, zu dem er gehört, in den JSONPath-Tester dieser Website ein, und er wählt genau diesen Knoten aus — der schnellste Weg, einen Unterschied in seiner Umgebung zu lesen.
- Es ist eine Abfrage gegen das Dokument, in dem der Knoten tatsächlich liegt: der Pfad eines hinzugefügten Mitglieds läuft auf dem zweiten Dokument, der eines entfernten auf dem ersten. Nichts hier benennt je einen Knoten, den es nicht gibt.
Eine geänderte Zeile kann zwei Pfade tragen, und darin scheint die Zuordnung des nächsten Abschnitts durch: sobald eine Liste ein Element gewonnen oder verloren hat, sitzt dasselbe Element auf jeder Seite an einem anderen Index. Wo beide Pfade gleich sind — und das ist fast immer der Fall — wird nur einer gezeigt.
Wie zwei Listen einander zugeordnet werden
Zwei Objekte werden Mitglied für Mitglied verglichen, was unkompliziert ist, weil ein Mitglied einen Namen hat. Zwei Listen haben keine Namen, nur Positionen, und sie Position für Position zu vergleichen ist das, was die meisten Vergleichsausgaben unlesbar macht: fügen Sie einen Datensatz vorn in eine lange Liste ein, und nichts ist mehr, wo es war, sodass ein Vergleich, der Position als Identität liest, die ganze Liste als verschieden meldet — im engen Sinn wahr und in jedem anderen nutzlos. Deshalb werden die Elemente zuerst einander zugeordnet, danach was sie sind und nicht nach einem Feld, das Sie benennen, und gemeldet wird nur, was die Zuordnung übrig lässt.
{"hosts": ["alpha", "beta", "gamma"]}
{"hosts": ["alpha", "staging", "beta", "gamma"]}Das ist eine einzige Zeile: staging wurde bei $['hosts'][1] hinzugefügt. Die Elemente namens beta und gamma sind um eins weitergerückt und werden nicht erwähnt, denn sich bewegen ist nicht sich ändern. Dieselbe Zuordnung ist es auch, die ein einzelnes geändertes Feld innerhalb eines Listenelements als Änderung an diesem Feld melden lässt statt als Ersetzung des ganzen Elements durch ein anderes.
Die Reihenfolge zählt weiterhin, und die Zuordnung tut nicht so, als wäre es anders: [1, 2] gegen [2, 1] kommt als eine vorn entfernte 1 und eine nach der 2 hinzugefügte 1 zurück, und genau das ist geschehen. Zwei Listen können einander auch zu verschieden sein, als dass die Zuordnung ihren Aufwand wert wäre, und jenseits dieses Punktes fällt der Vergleich auf das Vorgehen Position für Position zurück und sagt es oben im Ergebnis — eine unruhige Antwort ist damit erklärt statt rätselhaft.
Der Bericht und der Baum
Derselbe Vergleich wird in zwei Darstellungen angeboten, und das Umschalten zwischen ihnen rechnet nichts neu: der Baum wird aus eben der Liste von Unterschieden gezeichnet, die der Bericht aufführt, sodass die beiden weder darüber uneins sein können, was sich geändert hat, noch darüber, wie viel es ist.
- Der Bericht beantwortet, was sich geändert hat: eine Zeile je Unterschied, jede mit ihrem Pfad, ihrer Art und ihrem Wert auf beiden Seiten. Das ist die Ansicht zum Überfliegen, wenn Sie die ganze Liste vor sich haben wollen.
- Der Baum beantwortet, wo im Dokument: die beiden Dokumente zu einer Gliederung verschmolzen, und offen nur die Teile, die einen Unterschied enthalten. Jede Folge aufeinanderfolgender Kinder ohne Inhalt klappt zu einer Zeile zusammen, die sagt, für wie viele sie steht — das Paar aus dem Abschnitt darüber zeichnet sich als fünf Zeilen: das Dokument, die Liste darin, eine zusammengeklappte Zeile für ein Element, das hinzugefügte Element und eine zusammengeklappte Zeile für zwei.
- Die Zahl neben der Überschrift des Ergebnisses sind alle Unterschiede, die es gibt. Wenn die Liste auf dem Bildschirm der Länge wegen abgeschnitten wird, bewegt sich diese Zahl nicht, und eine Schaltfläche am Fuß der Liste zeigt den Rest.
~! $['port'] 8080 -> "8080" - $['debug'] true + $['retries'] 3
Das ist es, was die Kopieren-Schaltfläche für die beiden Dokumente aus dem dritten Abschnitt erzeugt: ein Zeichen für die Art, dann der Pfad, dann die Werte mit einem Pfeil dazwischen — ein Plus für ein hinzugefügtes Mitglied, ein Minus für ein entferntes, eine Tilde für eine Änderung und eine Tilde mit Ausrufezeichen, wo sich zusätzlich der Typ geändert hat. Es steht mit Absicht in Symbolen und nicht in Wörtern da, damit ein eingefügtes Ergebnis derselbe Text ist, in welcher der Sprachen dieser Website Sie auch gelesen haben, und es kürzt nichts: ein Wert, den der Bildschirm abgeschnitten hat, steht dort vollständig.
Was das Parsen kostet, und was das Werkzeug laut ausspricht
Zu vergleichen, wozu zwei Dokumente geparst werden, heißt mit dem zu leben, was das Parsen kostet, und JSON zu parsen ist nicht verlustfrei. Das wiegt hier schwerer als irgendwo sonst auf dieser Website, denn die Antwort, die ein Vergleichswerkzeug sich am wenigsten leisten darf, ist „kein Unterschied“ zwischen zwei Dokumenten, die sich sehr wohl unterscheiden. Deshalb wird der Text jedes Bereichs ein zweites Mal als Text gelesen, und was das Parsen fallen ließ, wird neben dem Vergleich gemeldet statt verschluckt.
- Ein Mitgliedsname, der zweimal im selben Objekt steht. Nur die spätere Kopie übersteht das Parsen, also wurde nur die spätere Kopie je verglichen und die frühere hat niemand gesehen.
- Eine Zahl, die zu lang ist, um als Double zu überleben. Zwei verschiedene Literale können zum selben Wert geparst werden, und Kennungen sind genau die Stelle, an der das passiert: 12345678901234567890 und 12345678901234567891 sind zwei verschiedene ganze Zahlen und eine geparste Zahl, sodass der Vergleich für sich genommen zwei Dokumente identisch nennen würde, deren Kennungen sich unterscheiden.
{"user": {"id": 1}, "user": {"id": 2}}Dieses Dokument wird zu {"user": {"id": 2}} geparst, und das Werkzeug sagt es unter dem Bereich, in den es eingefügt wurde, mit Zeile und Spalte des ersten Falls und der Gesamtzahl. Keiner der beiden Verluste hält den Vergleich auf; beide stehen daneben. Ein Dokument, das sich überhaupt nicht parsen lässt, wird an derselben Stelle gemeldet, mit der Position des Problems, wo es eine zu nennen gibt, und die beiden Bereiche werden unabhängig gelesen — zwei kaputte Dokumente ergeben also zwei Fehler auf einmal statt einen nach dem anderen. Ein Dokument, das weit tiefer verschachtelt ist, als ein Wert gezeichnet werden kann, wird rundheraus abgelehnt, und das ist eine Ablehnung und kein hängender Tab.
Warum nichts von dem, was Sie einfügen, diesen Tab verlässt
Beide Dokumente bleiben in Ihrem Browser. Es gibt keinen Upload, keine Anfrage und keinen Server, der eine Kopie halten könnte: der Vergleich ist Rechnerei innerhalb der Seite, die Sie ohnehin schon geladen haben, weshalb er auch bei abgeschaltetem Netz weiterarbeitet. Das ist es, was es unbedenklich macht, eine Produktionsantwort, einen Kundendatensatz oder eine signierte Nutzlast hier einzufügen.
Gespeichert wird ebenfalls nichts. Laden Sie die Seite neu, und beide Bereiche sind leer; es gibt keinen Verlauf, kein Konto und nichts, was hinterher zu löschen wäre. Das Einzige, was je hinausgeht, ist das, was Sie selbst herauskopieren.
Häufig gestellte Fragen
- Wird die Schlüsselreihenfolge ignoriert?
- Ja, immer, und das ist der Grund, warum es dieses Werkzeug gibt. Zwei Objekte mit denselben Mitgliedern und denselben Werten sind identisch, wie auch immer sie geschrieben wurden, also taucht ein Serialisierer, der seine Schlüssel bei jedem Lauf anders ausgibt, nie als Änderung auf. Einrückung, Minifizierung, die Schreibweise einer Zahl und die Maskierung eines Zeichens werden aus demselben Grund ignoriert, und nichts davon ist eine Einstellung, die Sie hätten anders setzen können.
- Ist ein Mitglied mit dem Wert null dasselbe wie ein Mitglied, das fehlt?
- Nein, und es gibt keine Möglichkeit, sie gleich zu behandeln. {"note": null} gegen {} wird als $['note'] entfernt gemeldet. Ein vorhandenes leeres Feld ist eine andere Aussage als ein Feld, das niemand geschickt hat — jede Schemasprache und jede statisch typisierte Sprache hält die beiden auseinander —, sodass sie hier zusammenzuwerfen etwas wegwerfen würde, was die Dokumente tatsächlich sagen.
- Werden [1, 2] und [2, 1] als gleich gemeldet?
- Nein. Ein JSON-Array ist geordnet, also sind zwei Listen mit denselben Elementen in anderer Reihenfolge zwei verschiedene Dokumente, und sie gleich zu nennen hieße, dieses Werkzeug etwas Falsches über das Format sagen zu lassen. Sie bekommen eine Entfernung und eine Hinzufügung: die 1 wurde vorn entfernt und nach der 2 wieder hinzugefügt. Bei Objekten ist es umgekehrt, weil ihre Mitglieder benannt und nicht positioniert sind.
- Was bedeutet der Pfad in jeder Zeile?
- Er ist die Stelle, an der der Unterschied im Dokument sitzt, geschrieben als normalisierter Pfad nach RFC 9535: $ ist das Dokument selbst, $['port'] ein Mitglied davon, $['hosts'][1] das Element mit Index 1 der Liste unter hosts. Er ist zugleich eine Abfrage, die Sie ausführen können — fügen Sie ihn zusammen mit dem Dokument, zu dem er gehört, in den JSONPath-Tester dieser Website ein, und er wählt genau diesen Knoten aus und sonst keinen.
- Warum zeigte eine Zeile zwei verschiedene Pfade?
- Weil das Zuordnen zweier Listen dasselbe Element auf jeder Seite an einem anderen Index lassen kann. Vergleichen Sie ["alpha", "beta"] mit ["intro", "alpha", "beta!"], und Sie erhalten zwei Zeilen: intro wurde bei $[0] hinzugefügt, und beta wurde zu beta! — was im ersten Dokument $[1] ist und im zweiten $[2]. Wo die beiden Pfade gleich sind, und das sind sie meistens, wird nur einer gezeigt.
- Was bedeutet ein Typwechsel in einer Zeile?
- Dass der Wert nicht bloß anders ist, sondern eine andere Art von Sache: eine Zahl, die zur Zeichenkette wurde, ein Wert, der zu null wurde, ein Objekt, das zur Liste wurde. Ein Port, der auf der einen Seite 8080 und auf der anderen "8080" geschrieben ist, ist der häufigste Fall, und er bedeutet meist, dass sich ein Serialisierer oder ein Client geändert hat und nicht die Daten. Er wird in der Zeile markiert, weil ein bearbeiteter Wert und ein abdriftender Vertrag von Ihnen verschiedene Reaktionen verlangen.
- Meine beiden Dokumente sehen gleich aus, aber eines schreibt denselben Schlüssel zweimal. Was passiert?
- Das Parsen behält die spätere Kopie und lässt die frühere fallen, also sieht der Vergleich ein einziges Mitglied und meldet womöglich gar keinen Unterschied. Das Werkzeug liest den Rohtext genau deswegen getrennt und sagt unter diesem Bereich, dass ein Name zweimal geschrieben steht, wie oft insgesamt und wo der erste sitzt. Dasselbe zweite Lesen fängt eine ganze Zahl ab, die zu lang ist, um als Double zu überleben — die andere Art, auf die zwei Dokumente, die sich unterscheiden, zu zweien geparst werden können, die es nicht tun.
- Bekomme ich einen Patch, den ich anwenden kann?
- Nein, und das ist eine Entscheidung und kein Versäumnis. Ein JSON Patch wird eine Operation nach der anderen angewendet, sodass sich die Indizes darin während des Laufs verschieben; einen auszugeben ist ein Versprechen über ein Programm, das Sie gegen Ihre eigenen Daten laufen ließen, und das ist eine weit größere Behauptung, als zu beschreiben, was sich unterscheidet. Mitnehmen können Sie stattdessen den Bericht als Text, über die Kopieren-Schaltfläche — in jeder Sprache der Website derselbe und nirgends gekürzt.
- Wird irgendetwas, was ich einfüge, an einen Server geschickt?
- Nein. Beide Dokumente werden in Ihrem Browser verglichen, und keines verlässt ihn: kein Upload, keine Anfrage und nichts, was zwischen Besuchen aufbewahrt wird. Das ist es, was es unbedenklich macht, eine Produktionsantwort einzufügen, und deshalb arbeitet das Werkzeug auch bei abgeschaltetem Netz weiter. Laden Sie die Seite neu, und beide Bereiche sind wieder leer.
Verwandte Werkzeuge
- Text-Diff
Wenn die Änderung, die Sie sehen wollen, in der Formatierung steckt und nicht in den Daten — ein Einrückungsdurchlauf, ein verschobener Schlüssel oder zwei Dateien, die gar kein JSON sind —, zeigt sie nur ein Vergleich Zeile für Zeile. Genau das tut jene Seite, mit Optionen für Leerzeichen und Schreibung und einem kopierbaren Patch.
- JSON-Formatierer
Validiert und verschönert JSON, mit klaren Fehlerstellen.
- SQL-Formatierer
Formatiert und verschönert SQL – mehrere Dialekte.
- XML-Formatierer
Formatiert und prüft XML – verschönern oder minimieren.