Français

Outils de développement · JSON formateur et validateur

L'ordre des clés est-il important en JSON ? Ordre, égalité et RFC 8785 normes

· Contexte

json normes validation

L'ordre des clés est-il important en JSON ? Ordre, égalité et RFC 8785 illustrés avec des jetons JSON et une limite de validation précise
Illustration vectorielle originale de ToolAcre

La spécification JSON appelle les objets non ordonnés, mais les vrais analyseurs et sérialiseurs préservent généralement l'ordre et les schémas de signature en dépendent. Cet article explique ce que dit la spécification, ce que font les implémentations et comment la canonisation résout la tension.

Mêmes données, octets différents

`{"city":"Oslo","temp":4}` et `{"temp":4,"city":"Oslo"}` contiennent les deux mêmes noms et valeurs, mais leurs octets sources diffèrent. L'indentation peut ajouter beaucoup plus de différences textuelles sans modifier aucune des valeurs analysées. C'est pourquoi « égal JSON » a besoin d'une règle de comparaison : comparez-vous du texte, des objets analysés ou une représentation canonique définie par un autre protocole ?

ToolAcre peut supprimer le bruit des espaces en formatant les deux documents avec la même indentation. Il peut également trier de manière récursive les clés d'objet lorsque cette option est sélectionnée. Le tri modifie délibérément l'ordre des membres mais ne déplace jamais les éléments du tableau, car la position du tableau représente les données. Ni le formatage ordinaire ni ce tri facultatif ne produisent le RFC 8785 canonique JSON, donc la sortie ne doit pas être remplacée par un format de signature spécifié.

Ce que dit la RFC 8259 — un objet est une collection non ordonnée de paires name/value, et les implémentations peuvent exposer l'ordre ou non

RFC 8259 décrit un objet comme une collection non ordonnée de paires name/value. Par conséquent, un logiciel qui traite l'ordre des membres comme la signification d'un objet JSON ordinaire s'appuie sur un comportement en dehors de ce modèle abstrait. Les tableaux sont explicitement ordonnés, donc `["draft","final"]` n'est pas interchangeable avec `["final","draft"]`. L'ordre des objets et l'ordre des tableaux ne doivent jamais être normalisés par la même règle.

La RFC note également que les bibliothèques diffèrent selon qu'elles exposent ou non l'ordre des membres aux appelants. Cet avertissement est suffisant pour une conception portable : n'encodez pas la priorité ou la séquence en plaçant un membre d'objet avant un autre. Si la séquence est importante, représentez-la avec un tableau ou un champ explicite. Un formateur affichant un ordre stable est pratique pour les humains, mais il ne transforme pas la position en une propriété de niveau standard de l'objet.

Ce que fait réellement ce formateur

Le tri étant désactivé, ToolAcre analyse le document et sérialise la valeur JavaScript résultante. La sortie suit le comportement d'énumération des propriétés JavaScript plutôt que de conserver le flux de jetons d'origine octet par octet. La plupart des clés de chaîne ordinaires apparaissent dans un ordre familier, tandis que les noms de type index entier peuvent être émis avant les autres noms. Les choix d’orthographe et d’échappement des nombres peuvent également être normalisés lors de la resérialisation.

Lorsque le tri est activé, le formateur crée de nouveaux objets dont les propres clés sont classées par ordre alphabétique pour chaque objet imbriqué. Pour `{"z":{"b":1,"a":2},"items":[{"d":4,"c":3},"x"]}`, les noms d'objet deviennent `items`, `z` ; les noms d'objets imbriqués sont également triés ; et le tableau contient toujours son objet avant `"x"`. Trier des objets à l'intérieur d'un tableau ne signifie pas trier le tableau lui-même.

Quand l'ordre des octets est important

L'ordre textuel est important chaque fois qu'un processus consomme des octets exacts plutôt que la valeur abstraite. Un hachage de fichier, une clé de cache, une signature numérique ou une différence basée sur une ligne change lorsque les membres se déplacent ou que les espaces changent. Cela ne contredit pas le modèle objet non ordonné ; cela signifie que le processus environnant a choisi une représentation en octets dans le cadre de son entrée. Les règles de représentation doivent alors être explicites et partagées.

Pour les révisions de routine, une indentation cohérente et un tri alphabétique facultatif peuvent faciliter la visualisation des modifications. Pour le travail cryptographique ou protocolaire, « semble stable » n’est pas un contrat. Le producteur et le vérificateur doivent utiliser l'algorithme de canonisation exact requis par leur protocole avant le hachage ou la signature. Si aucun algorithme n'est nommé, ne supposez pas que la sortie de ToolAcre correspondra à un autre sérialiseur selon les versions, les exécutions ou les valeurs de cas extrêmes.

Pourquoi le tri des clés n'est pas RFC 8785

RFC 8785 définit le schéma de canonisation JSON pour produire des octets répétables à partir de données compatibles. Son travail va plus loin que le simple classement des clés par ordre alphabétique. Il spécifie le tri des propriétés déterministes ainsi qu'un comportement de sérialisation exact pour les chaînes et les nombres et impose des contraintes sur le modèle d'entrée. Une jolie indentation ne fait pas partie de la sortie canonique et le tri tenant compte des paramètres régionaux n'est pas une approximation acceptable.

ToolAcre ne fait aucune réclamation RFC 8785. Son option de tri est une fonctionnalité de lisibilité superposée à `JSON.parse` et `JSON.stringify` ; il ne valide pas les conditions préalables I-JSON et ne remplace pas les règles de sérialisation de la RFC. Une valeur telle que `1e-7`, une clé contenant des caractères non-ASCII ou une chaîne d'échappement peut révéler des différences entre un formateur trié occasionnel et un canonicaliseur conforme. Utilisez une implémentation JCS testée lorsque JCS est requis.

Exemple concret : comparer équitablement deux documents

Comparez `{"meta":{"rev":2,"owner":"Mira"},"steps":["cut","pack"]}` avec `{"steps":["cut","pack"],"meta":{"owner":"Mira","rev":2}}`. Formatez les deux avec deux espaces et le tri désactivé : les espaces deviennent cohérents, mais l'ordre des membres racine et imbriqués peut toujours différer. Analysez les deux et comparez leurs champs prévus pour établir une équivalence au niveau de la valeur plutôt que de déclarer le texte brut égal.

Activez le tri récursif des clés et les deux exemples s'affichent avec le même ordre d'objet tandis que `steps` reste `cut` puis `pack`. C'est utile pour une différence humaine, mais c'est toujours la normalisation de ToolAcre, pas la preuve RFC 8785. Si le deuxième tableau était `["pack","cut"]`, les clés de tri laisseraient correctement cette différence visible car changer le tableau modifierait la séquence représentée.

Ce que cela ne couvre pas

Le tri des clés ne définit pas une égalité profonde pour chaque application. Les noms en double sont acceptés par `JSON.parse`, qui conserve la dernière valeur, de sorte que le formatage peut effacer la preuve qu'une source contenait des répétitions. Les grands entiers ont peut-être déjà perdu en précision dans la valeur JavaScript. Un domaine peut également traiter les tableaux sélectionnés comme des ensembles, mais ToolAcre ne peut pas déduire cette règle et ne réorganise donc jamais les tableaux.

Le formateur ne compare pas non plus les schémas, n'applique pas les valeurs par défaut, ne normalise pas Unicode ou ne décide pas si deux représentations numériques sont acceptables pour un système en aval. Ce sont des contrats distincts. Utilisez le formatage pour réduire le bruit de présentation, une comparaison structurelle spécialement conçue pour l'égalité des valeurs et le canonicaliseur spécifié pour les octets exacts. Mélanger ces emplois sous le mot « normaliser » crée une fausse confiance quant à ce qui a réellement été comparé.

À retenir : l'ordre est insignifiant pour le modèle et significatif pour les octets

L'ordre des membres de l'objet n'a pas de signification dans le modèle de données RFC 8259, contrairement à l'ordre des tableaux. Les octets sources enregistrent toujours à la fois l'ordre et les espaces, de sorte que les hachages, les signatures et les différences de texte observent des distinctions qu'une comparaison orientée valeur peut ignorer. Indiquez quelle couche est importante avant de choisir un outil : l'identité textuelle, l'équivalence des valeurs analysées et l'identité canonique définie par le protocole sont trois questions différentes.

ToolAcre ne prend en charge les deux premiers flux de travail qu'indirectement : un formatage cohérent clarifie les différences textuelles et le tri alphabétique récursif des objets et des clés peut rendre les comparaisons humaines plus silencieuses. Les tableaux ne sont jamais triés. Le résultat n'est pas RFC 8785 canonique JSON et ne doit pas être signé comme s'il l'était. Préservez l'entrée originale lorsque la preuve lexicale est importante, en particulier parce que l'analyse des clés en double ne conserve que la dernière valeur.