À l'aide de jq ou alternative outils de ligne de commande pour comparer des fichiers JSON
Existe-il des utilitaires de ligne de commande qui peut être utilisé pour savoir si deux fichiers JSON sont identiques à celles de l'invariance dans le dictionnaire-clés et à l'intérieur de la liste d'élément de commande?
Cela pourrait-il être fait avec jq
ou de quelque autre outil équivalent?
Exemples:
Ces deux fichiers JSON sont identiques
A
:
{
"People": ["John", "Bryan"],
"City": "Boston",
"State": "MA"
}
B
:
{
"People": ["Bryan", "John"],
"State": "MA",
"City": "Boston"
}
mais ces deux fichiers JSON sont différentes:
A
:
{
"People": ["John", "Bryan", "Carla"],
"City": "Boston",
"State": "MA"
}
C
:
{
"People": ["Bryan", "John"],
"State": "MA",
"City": "Boston"
}
Qui serait:
$ some_diff_command A.json B.json
$ some_diff_command A.json C.json
The files are not structurally identical
- Fichier
A
et fichierB
ne sont pas identiques. Vous interpréter la valeur de la cléPeople
comme un ensemble, mais c'est une liste et l'ordre de la liste ne peut pas, en général, être considéré négligeable. ChangementPeople
àWinners_by_ranking
, et il devient immédiatement louche de prétendre que les fichiers sont identiques.
Vous devez vous connecter pour publier un commentaire.
Depuis jq de comparaison déjà compare les objets sans prendre en compte la commande de clés, tout ce qui reste est de trier toutes les listes à l'intérieur de l'objet avant de les comparer. En supposant que vos deux fichiers sont nommés
a.json
etb.json
, sur la dernière jq tous les soirs:Ce programme doit retourner "true" ou "false" selon si oui ou non les objets sont égaux à l'aide de la définition de l'égalité que vous demandez.
EDIT: Le
(.. | arrays) |= sort
construire ne fonctionne pas comme prévu sur certains cas limites. Cette question GitHub explique pourquoi et fournit quelques solutions de rechange, telles que:Appliquée à l'jq invocation ci-dessus:
--argfile a a.json
pour--arg a $a
(soit $a une chaîne json), avec pas de chance. une idée de comment l'approche de chaînes, pas de fichiers?En principe, si vous avez accès à bash ou une autre avancée de shell, vous pourriez faire quelque chose comme
à l'aide de sous-processus. Ce sera le format json avec triés clés, et une représentation systématique de floating points. Ce sont les deux seules raisons que je pense de pour pourquoi json avec le même contenu sera imprimée différemment. Donc faire une simple comparaison de chaînes de caractères seront ensuite les résultats dans un test approprié. C'est probablement aussi important de noter que si vous ne pouvez pas utiliser bash, vous pouvez obtenir les mêmes résultats avec des fichiers temporaires, c'est juste pas aussi propre.
Ce n'est pas tout à fait répondre à votre question, parce que dans la façon dont vous l'avez indiqué à la question que vous vouliez
["John", "Bryan"]
et["Bryan", "John"]
à comparer de la même manière. Depuis json n'est pas le concept d'un jeu, seulement une liste, ceux-ci devraient être considérées comme distinctes. L'ordre est important pour les listes. Vous devez écrire certains de comparaison personnalisé si vous en voulait comparer aussi, et pour ce faire, vous devez définir ce que vous entendez par l'égalité. N'afin d'importance pour toutes les listes ou seulement une partie? Que sur les éléments en double? Sinon, si vous voulez être représenté comme un ensemble, et les éléments sont des chaînes, vous pouvez les mettre dans des objets comme des{"John": null, "Bryan": null}
. L'ordre n'a pas d'importance lorsque l'on compare ceux pour l'égalité.Mise à jour
De commentaire la discussion: Si vous voulez obtenir une meilleure idée de pourquoi le json n'est pas le même, alors
produira plus interprétables de sortie.
vimdiff
pourrait être préférable de diff selon les goûts.jq
jq
ne posix style arguments de sorte que vous pouvez avoir à invoquerjq -c -S ...
vimdiff <(jq -S . a.json) <(jq -S . b.json)
-c
(ce qui rend la sortie compact), préférences de style n'est pas pertinent pour votre réponse.c
n'est pas strictement nécessaire, mais pour moi, il n'y a pas de raison pour le cmp de comparer identiques espaces, et aucune raison pour que jq à peine émission.diff
,vimdiff
, ou n'importe quel outil qui n'a de comparaison de fichiers de travail, maiscmp
est tout ce qui est nécessaire.cmp
. Pour être utile pour un rapide copier-coller, vous pourrait peut-être inclure un visual diff (par exemple à l'aide dediff
), bien 🙂Utilisation
jd
avec le-set
option:Pas de sortie pas de différence.
Différences sont indiquées comme @ path et + ou -.
La sortie de diff peut également être utilisé en tant que fichiers de patch avec la
-p
option.https://github.com/josephburnett/jd#command-line-usage
Voici une solution à l'aide de la fonction générique de marche/1:
Exemple:
produit:
Et enveloppé comme un script bash:
POSTSCRIPT: marche/1 est intégré dans les versions de jq > 1.5, et peut donc être omis si votre jq il comprend, mais il n'y a pas de mal à l'inclure de manière redondante dans un jq script.
POST-post-scriptum: Le groupe builtin version de
walk
a récemment été modifiée de sorte qu'il n'est plus trie les clés à l'intérieur d'un objet. Plus précisément, il utilisekeys_unsorted
. Pour la tâche à portée de main, la version à l'aidekeys
doit être utilisé.walk
a été ajouté dans jq 1.5. J'ai été désireux d'un compromis opérateur entrefilter
etmap
et il ressemble à ce qu'il est.Peut-être que vous pourriez utiliser ce genre et outil de comparaison: http://novicelab.org/jsonsortdiff/ qui, la première, trie les objets sémantiquement et compare. Il est basé sur https://www.npmjs.com/package/jsonabc
Si vous aussi vous voulez voir les différences, à l'aide de @Erik de répondre, en tant que source d'inspiration et js-embellir:
-c
de lajq
ligne de commande. Je ne sais pas, préfère ne pas introduire d'inutile à outils 😉