2016-07-08 10 views
5

Ich möchte zwei JSON-Textdateien unterscheiden. Leider sind sie in beliebiger Reihenfolge aufgebaut, daher erhalte ich Diffs, wenn sie semantisch identisch sind. Ich würde gerne jq (oder was auch immer) verwenden, um sie in irgendeiner Art von vollständiger Reihenfolge zu sortieren, um Unterschiede aufgrund der Reihenfolge der Elemente zu eliminieren.Wie kann ich JSON vollständig mit jq sortieren?

--sort-keys löst das halbe Problem, aber Arrays werden nicht sortiert.

Ich bin ziemlich ignorant von jq und weiß nicht, wie man einen jq rekursiven Filter schreibt, der alle Daten erhält; jede Hilfe würde geschätzt werden.

Ich erkenne, dass zeilenweise 'diff' Ausgabe ist nicht unbedingt der beste Weg, um zwei komplexe Objekte zu vergleichen, aber in diesem Fall weiß ich, dass die beiden Dateien sehr ähnlich sind (fast identisch) und Zeile-für- Linien Diffs sind gut für meine Zwecke.

Using jq or alternative command line tools to diff JSON files antwortet eine sehr ähnliche Frage, aber druckt nicht die Unterschiede. Außerdem möchte ich die sortierten Ergebnisse speichern, also was ich wirklich will, ist nur ein Filterprogramm, um JSON zu sortieren.

+2

Mögliches Duplikat [Mit jq oder alternativen Kommandozeilen-Tool zu diff JSON-Dateien] (http://stackoverflow.com/questions/31930041/using-jq-or-alternative-command- line-tools-to-diff-json-files) –

Antwort

5

Hier ist eine Lösung mit einer generischen Funktion sorted_walk/1 (so benannt für den Grund in dem Postskript beschrieben unten).

normalize.jq:

# Apply f to composite entities recursively using keys[], and to atoms 
def sorted_walk(f): 
    . as $in 
    | if type == "object" then 
     reduce keys[] as $key 
     ({}; . + { ($key): ($in[$key] | sorted_walk(f)) }) | f 
    elif type == "array" then map(sorted_walk(f)) | f 
    else f 
    end; 

def normalize: sorted_walk(if type == "array" then sort else . end); 

normalize 

Beispiel mit bash:

diff <(jq -S -f normalize.jq FILE1) <(jq -S -f normalize.jq FILE2) 

POSTSCRIPT-: Die eingebaute Definition von walk/1 überarbeitet wurde nach dieser Antwort wurde zuerst veröffentlicht: es nutzt jetzt keys_unsorted anstatt keys.

+0

Genau das, was ich brauchte, danke! Ich sehe, dass Sie eine Variation dieser Lösung im zugehörigen Beitrag gepostet haben, aber das einfachere Beispiel hat hier eine Reihe von Fragen beantwortet. –

3

Ich möchte zwei JSON-Textdateien unterscheiden.

Verwenden jd mit der -set Option:

keine Ausgabe keinen Unterschied bedeutet.

$ jd -set A.json B.json 

Unterschiede werden als @ Pfad und + oder - dargestellt.

$ jd -set A.json C.json 

@ ["People",{}] 
+ "Carla" 

Die Ausgänge Differentiale auch als Patch-Dateien mit der -p Option verwendet werden.

$ jd -set -o patch A.json C.json; jd -set -p patch B.json 

{"City":"Boston","People":["John","Carla","Bryan"],"State":"MA"} 

https://github.com/josephburnett/jd#command-line-usage