Comparer du JSON
Compare deux documents par structure : reformater ou réordonner les clés ne compte pas.
Rien de ce que vous collez ne quitte votre navigateur. La liste d’autorisation connect-src en fait une garantie du navigateur plutôt qu’une promesse. Vérifiez-le vous-même
Ceci compare deux documents par structure et non par ligne. Reformatez l’un d’eux, triez ses clés, changez son indentation : le diff reste vide, parce que rien de tout cela n’a changé les données.
Un diff textuel sur du JSON est quasiment inutile pour exactement cette raison. Re-sérialisez un document avec une autre bibliothèque et chaque ligne apparaît modifiée alors que rien ne l’est.
Ce qui compte comme différence
Quatre types de changement, chacun signalé avec un JSON Pointer vers l’emplacement exact.
- Ajouté
- Une clé ou un élément présent à droite et absent à gauche.
- Supprimé
- Présent à gauche et absent à droite.
- Modifié
- Présent des deux côtés avec une valeur différente du même type.
- Type changé
- Présent des deux côtés avec un type différent. Cela mérite d’être séparé, car un nombre devenu chaîne est en général un bug de sérialisation plutôt qu’un changement de données.
Comment les tableaux sont comparés, et pourquoi cela compte
Les tableaux sont la partie difficile de tout diff structurel, et il n’existe pas une seule bonne réponse.
Comparer position par position est correct pour un tuple de forme fixe et catastrophique pour une liste. Insérez un élément en tête d’un tableau de mille éléments et toutes les positions suivantes apparaissent modifiées, ce qui enterre l’unique vraie différence sous mille fausses.
Cet outil effectue à la place une passe de plus longue sous-séquence commune, si bien qu’une insertion est signalée comme une insertion. Cela coûte un temps proportionnel au produit des deux longueurs : au-delà d’un seuil, il repasse à la comparaison positionnelle et le dit dans les notes. Il ne se dégrade jamais en silence.
Ce qui n’est délibérément pas une différence
- L’ordre des clés
- Les objets JSON ne sont pas ordonnés d’après la spécification. Deux documents contenant les mêmes membres dans un ordre différent sont le même document.
- Espaces et indentation
- Non significatifs pour un analyseur, donc invisibles ici.
- 0 et -0
- Distincts selon Object.is mais identiques en tant que nombres JSON.
How to do this in code
Comparaison structurelle en code.
sh jq
La première ligne est celle à retenir. Trier les clés d’abord supprime l’essentiel du bruit d’un diff textuel.
# Sort keys recursively, then diff the text. Cheap and
# surprisingly effective for small documents.
diff <(jq -S . a.json) <(jq -S . b.json)
# Keys present in one and not the other
jq -n --slurpfile a a.json --slurpfile b b.json \
'($a[0] | paths) - ($b[0] | paths)' py Python
from deepdiff import DeepDiff
diff = DeepDiff(a, b, ignore_order=True)
print(diff)
# Standard library only, for a shallow comparison
changed = {k for k in a.keys() | b.keys() if a.get(k) != b.get(k)} js JavaScript
JSON Patch est le format d’échange standard pour un diff JSON, et ses chemins sont des pointeurs RFC 6901 comme ceux que signale cet outil.
import { compare } from 'fast-json-patch';
// RFC 6902 JSON Patch: a list of operations that turns a into b
const patch = compare(a, b);
// [{ op: 'replace', path: '/user/name', value: 'Priya' }] go Go
go-cmp est le choix standard dans les tests Go et produit une sortie lisible pour les structures imbriquées.
import "github.com/google/go-cmp/cmp"
if d := cmp.Diff(a, b); d != "" {
t.Errorf("mismatch (-want +got):\n%s", d)
} Questions fréquentes
- Pourquoi réordonner les clés ne montre-t-il aucune différence ?
- Parce que la RFC 8259 définit un objet comme une collection non ordonnée. En pratique tous les analyseurs conservent l’ordre d’insertion, et les diffs qui en dépendent testent la sérialisation plutôt que les données.
- Puis-je ignorer des champs comme les horodatages ?
- Oui. Ignorer un chemin le retire entièrement de la comparaison : c’est ainsi qu’on compare deux réponses d’API qui ne diffèrent que par requestId et generatedAt.
- Qu’est-ce qu’un JSON Pointer ?
- La RFC 6901 : un chemin séparé par des barres obliques, comme /users/0/email. Deux caractères doivent être échappés à l’intérieur d’une clé : ~ devient ~0 et / devient ~1. Chaque changement signalé ici en porte un, ce qui permet d’adresser l’emplacement par programme.