Deutsch

Entwicklertools · JSON Formatierer und Validator

Spielt die Schlüsselreihenfolge in JSON eine Rolle? Ordnung, Gleichheit und RFC 8785

· Hintergrund

json Standards Validierung

Spielt die Schlüsselreihenfolge in JSON eine Rolle? Reihenfolge, Gleichheit und RFC 8785 veranschaulicht mit JSON-Tokens und einer präzisen Validierungsgrenze
Original-ToolAcre-Vektorillustration

Die JSON-Spezifikation ruft Objekte als ungeordnet auf, aber echte Parser und Serialisierer bewahren normalerweise die Reihenfolge, und Signaturschemata hängen davon ab. In diesem Beitrag wird entwirrt, was die Spezifikation sagt, was Implementierungen bewirken und wie die Kanonisierung die Spannungen löst.

Gleiche Daten, unterschiedliche Bytes

`{"city":"Oslo","temp":4}` und `{"temp":4,"city":"Oslo"}` enthalten dieselben zwei Namen und Werte, ihre Quellbytes unterscheiden sich jedoch. Durch die Einrückung können viele weitere Textunterschiede hinzugefügt werden, ohne dass sich einer der analysierten Werte ändert. Aus diesem Grund benötigt „gleich JSON“ eine Vergleichsregel: Vergleichen Sie Text, analysierte Objekte oder eine kanonische Darstellung, die durch ein anderes Protokoll definiert ist?

ToolAcre kann Leerzeichenrauschen entfernen, indem beide Dokumente mit derselben Einrückung formatiert werden. Wenn diese Option ausgewählt ist, können Objektschlüssel auch rekursiv sortiert werden. Beim Sortieren wird die Reihenfolge der Elemente absichtlich geändert, Array-Elemente werden jedoch nie verschoben, da die Array-Position Daten darstellt. Weder die normale Formatierung noch diese optionale Sortierung erzeugen den kanonischen RFC 8785 JSON, daher darf die Ausgabe nicht durch ein angegebenes Signaturformat ersetzt werden.

Was RFC 8259 sagt – ein Objekt ist eine ungeordnete Sammlung von Namen/value-Paaren, und Implementierungen können die Reihenfolge offenlegen oder nicht

RFC 8259 beschreibt ein Objekt als eine ungeordnete Sammlung von Namen/value-Paaren. Daher ist Software, die die Reihenfolge der Mitglieder als die Bedeutung eines gewöhnlichen JSON-Objekts behandelt, auf Verhalten außerhalb dieses abstrakten Modells angewiesen. Arrays sind explizit geordnet, daher ist `["draft","final"]` nicht mit `["final","draft"]` austauschbar. Objektreihenfolge und Array-Reihenfolge dürfen niemals durch dieselbe Regel normalisiert werden.

Der RFC stellt außerdem fest, dass sich Bibliotheken darin unterscheiden, ob sie Aufrufern die Mitgliederreihenfolge offenlegen. Diese Warnung reicht für tragbares Design aus: Kodieren Sie keine Priorität oder Reihenfolge, indem Sie ein Objektmitglied vor einem anderen platzieren. Wenn die Reihenfolge wichtig ist, stellen Sie sie mit einem Array oder einem expliziten Feld dar. Ein Formatierer, der eine stabile Reihenfolge anzeigt, ist für Menschen praktisch, wandelt die Position jedoch nicht in eine Eigenschaft des Objekts auf Standardebene um.

Was dieser Formatierer tatsächlich macht

Wenn die Sortierung deaktiviert ist, analysiert ToolAcre das Dokument und serialisiert den resultierenden JavaScript-Wert. Die Ausgabe folgt dem JavaScript-Eigenschaftenaufzählungsverhalten, anstatt den ursprünglichen Token-Stream Byte für Byte beizubehalten. Die meisten gewöhnlichen Zeichenfolgenschlüssel erscheinen in bekannter Reihenfolge, während Namen, die einem ganzzahligen Index ähneln, vor anderen Namen ausgegeben werden können. Auch die Schreibweise und Escape-Optionen für Zahlen können während der Reserialisierung normalisiert werden.

Wenn die Sortierung aktiviert ist, erstellt der Formatierer neue Objekte, deren eigene Schlüssel bei jedem verschachtelten Objekt alphabetisch sortiert sind. Für `{"z":{"b":1,"a":2},"items":[{"d":4,"c":3},"x"]}` lauten die Objektnamen `items`, `z`; Namen verschachtelter Objekte werden ebenfalls sortiert. und das Array enthält immer noch sein Objekt vor `"x"`. Das Sortieren von Objekten innerhalb eines Arrays bedeutet nicht, dass das Array selbst sortiert wird.

Wenn die Bytereihenfolge wichtig ist

Die Textreihenfolge ist immer dann wichtig, wenn ein Prozess exakte Bytes und nicht den abstrakten Wert verbraucht. Ein Datei-Hash, ein Cache-Schlüssel, eine digitale Signatur oder ein zeilenbasierter Diff ändert sich, wenn Mitglieder verschoben werden oder sich Leerzeichen ändern. Das widerspricht nicht dem ungeordneten Objektmodell; Dies bedeutet, dass der umgebende Prozess eine Byte-Darstellung als Teil seiner Eingabe ausgewählt hat. Die Darstellungsregeln müssen dann explizit und gemeinsam sein.

Bei routinemäßigen Überprüfungen können Änderungen durch konsistente Einrückung und optionale alphabetische Sortierung leichter erkennbar sein. Für kryptografische oder Protokollarbeiten ist „sieht stabil aus“ kein Vertrag. Der Produzent und der Verifizierer müssen vor dem Hashing oder Signieren den genauen Kanonisierungsalgorithmus verwenden, der in ihrem Protokoll erforderlich ist. Wenn kein Algorithmus benannt ist, gehen Sie nicht davon aus, dass die Ausgabe von ToolAcre über Versionen, Laufzeiten oder Randfallwerte hinweg mit einem anderen Serialisierer übereinstimmt.

Warum die Schlüsselsortierung nicht RFC ist 8785

RFC 8785 definiert das JSON Kanonisierungsschema zur Erzeugung wiederholbarer Bytes aus kompatiblen Daten. Seine Arbeit ist umfassender als die alphabetische Reihenfolge der Schlüssel. Es spezifiziert die deterministische Eigenschaftssortierung zusammen mit dem genauen Serialisierungsverhalten für Zeichenfolgen und Zahlen und erlegt dem Eingabemodell Einschränkungen auf. Eine hübsche Einrückung ist nicht Teil der kanonischen Ausgabe und eine ortsspezifische Sortierung ist keine akzeptable Annäherung.

ToolAcre erhebt keinen Anspruch auf RFC 8785. Seine Sortieroption ist eine Lesbarkeitsfunktion, die über `JSON.parse` und `JSON.stringify` geschichtet ist; Es validiert weder die I-JSON-Vorbedingungen noch ersetzt es die Serialisierungsregeln des RFC. Ein Wert wie `1e-7`, ein Schlüssel, der Nicht-ASCII-Zeichen enthält, oder eine Escape-Zeichenfolge können Unterschiede zwischen einem zufällig sortierten Formatierer und einem konformen Canonicalizer aufdecken. Verwenden Sie eine getestete JCS-Implementierung, wenn JCS erforderlich ist.

Arbeitsbeispiel: Fairer Vergleich zweier Dokumente

Vergleichen Sie `{"meta":{"rev":2,"owner":"Mira"},"steps":["cut","pack"]}` mit `{"steps":["cut","pack"],"meta":{"owner":"Mira","rev":2}}`. Formatieren Sie beide mit zwei Leerzeichen und deaktivierter Sortierung: Leerzeichen werden konsistent, aber die Reihenfolge der Stamm- und verschachtelten Elemente kann sich weiterhin unterscheiden. Analysieren Sie beide und vergleichen Sie ihre beabsichtigten Felder, um eine Äquivalenz auf Werteebene herzustellen, anstatt den Rohtext für gleich zu erklären.

Aktivieren Sie die rekursive Schlüsselsortierung und beide Beispiele werden mit derselben Objektreihenfolge gerendert, während `steps` `cut` und dann `pack` bleibt. Das ist für einen menschlichen Diff nützlich, aber es ist immer noch die Normalisierung von ToolAcre und kein RFC-8785-Beweis. Wenn das zweite Array `["pack","cut"]` wäre, würden die Sortierschlüssel diesen Unterschied korrekt sichtbar lassen, da eine Änderung des Arrays die dargestellte Reihenfolge ändern würde.

Was dies nicht abdeckt

Die Schlüsselsortierung definiert nicht für jede Anwendung eine tiefe Gleichheit. Doppelte Namen werden von `JSON.parse` akzeptiert, wodurch der letzte Wert beibehalten wird, sodass durch die Formatierung Beweise dafür gelöscht werden können, dass eine Quelle Wiederholungen enthielt. Bei großen Ganzzahlen kann es sein, dass der JavaScript-Wert bereits an Präzision verloren hat. Eine Domäne kann ausgewählte Arrays auch als Mengen behandeln, aber ToolAcre kann diese Regel nicht ableiten und ordnet Arrays daher nie neu an.

Der Formatierer vergleicht auch keine Schemata, wendet keine Standardwerte an, normalisiert Unicode und entscheidet nicht, ob zwei Zahlendarstellungen für ein Downstream-System akzeptabel sind. Das sind separate Verträge. Verwenden Sie Formatierung, um Präsentationsrauschen zu reduzieren, einen speziell entwickelten Strukturvergleich für Wertegleichheit und den angegebenen Kanonisierer für genaue Bytes. Die Vermischung dieser Jobs unter dem Wort „normalisieren“ schafft falsches Vertrauen darüber, was tatsächlich verglichen wurde.

Fazit: Die Reihenfolge ist für das Modell unbedeutend und für die Bytes von Bedeutung

Die Reihenfolge der Objektmitglieder hat im RFC-Datenmodell 8259 keine Bedeutung, die Array-Reihenfolge hingegen schon. Quellbytes zeichnen weiterhin sowohl Reihenfolge als auch Leerzeichen auf, sodass Hashes, Signaturen und Textunterschiede Unterschiede beachten, die bei einem wertorientierten Vergleich möglicherweise ignoriert werden. Geben Sie an, welche Ebene wichtig ist, bevor Sie ein Tool auswählen: Textidentität, Äquivalenz geparster Werte und protokolldefinierte kanonische Identität sind drei verschiedene Fragen.

ToolAcre unterstützt die ersten beiden Arbeitsabläufe nur indirekt: Konsistente Formatierung verdeutlicht Textunterschiede und rekursive alphabetische Objektschlüsselsortierung kann menschliche Vergleiche leiser machen. Arrays werden niemals sortiert. Das Ergebnis ist nicht RFC 8785 kanonisch JSON und sollte nicht so signiert werden, als ob es so wäre. Behalten Sie die Originaleingabe bei, wenn lexikalische Beweise wichtig sind, insbesondere weil beim Parsen doppelter Schlüssel nur der letzte Wert erhalten bleibt.