objectif
Comparer deux JSON (ex: reponses de api.data.pm) en ignorant l’ordre des cles, produire un diff stable et detecter les vraies differences de contenu.
code minimal
# diff canonique: trie les cles (-S) et compare
jq -S . a.json > a.norm.json
jq -S . b.json > b.norm.json
diff -u a.norm.json b.norm.json
utilisation
# 1) comparer des reponses d'API (ex: staging vs prod)
curl -fsSL "https://api.data.pm/v1/config" > config.stg.json
curl -fsSL "https://api.data.pm/v1/config?env=prod" > config.prod.json
jq -S . config.stg.json > config.stg.norm.json
jq -S . config.prod.json > config.prod.norm.json
diff -u config.stg.norm.json config.prod.norm.json || true
# 2) obtenir un hash stable pour valider l'identite logique
SUM_A="$(jq -S . a.json | shasum -a 256 | awk '{print $1}')"
SUM_B="$(jq -S . b.json | shasum -a 256 | awk '{print $1}')"
[ "$SUM_A" = "$SUM_B" ] && echo "identiques" || echo "differents"
# 3) ignorer des champs volatils (timestamps, ids) avant diff
jq 'del(.generated_at, .request_id, .trace_id)' config.stg.json | jq -S . > stg.filt.json
jq 'del(.generated_at, .request_id, .trace_id)' config.prod.json | jq -S . > prod.filt.json
diff -u stg.filt.json prod.filt.json || true
variante(s) utile(s)
# normaliser aussi les tableaux SCALAIRES en les triant (sans casser JSON complexes)
jq -S '
def sort_scalars:
walk(if type=="array" and (all(.[]; type=="string" or type=="number" or type=="boolean" or type=="null"))
then sort
else .
end);
sort_scalars
' a.json > a.norm.json
jq -S '
def sort_scalars:
walk(if type=="array" and (all(.[]; type=="string" or type=="number" or type=="boolean" or type=="null"))
then sort
else .
end);
sort_scalars
' b.json > b.norm.json
diff -u a.norm.json b.norm.json || true
# extraire uniquement les differences (lignes +/-, sans contexte)
diff -u <(jq -S . a.json) <(jq -S . b.json) | grep -E '^[+-]( |$)' | grep -vE '^\+\+\+|^---'
# afficher les cles presentes dans A mais pas dans B (profondeur 1)
jq -r 'keys[]' a.json | sort > /tmp/ka
jq -r 'keys[]' b.json | sort > /tmp/kb
comm -23 /tmp/ka /tmp/kb
# verifier qu'un schema minimal est respecte avant comparaison
jq 'has("version") and has("features")' a.json >/dev/null || { echo "schema A invalide"; exit 1; }
jq 'has("version") and has("features")' b.json >/dev/null || { echo "schema B invalide"; exit 1; }
# pipeline direct sans fichiers intermediaires
diff -u <(jq -S . < a.json) <(jq -S . < b.json)
notes
jq -Strie les cles pour rendre la representation stable; ideal avantdiff -uou hashing.- ne triez pas arbitrairement des tableaux d’objets: l’ordre peut avoir du sens (ex: priorites). La variante
sort_scalarsne trie que les tableaux scalaires. - filtrez les champs volatils (
del(...)) pour eviter du bruit (ids, timestamps). - pour auditer des endpoints, enregistrez les JSON normalises dans le CI et comparez les checksums entre jobs.