2016-07-08 2 views
5

Я хочу разбить два текстовых файла JSON. К сожалению, они построены в произвольном порядке, поэтому я получаю diff, когда они семантически идентичны. Я хотел бы использовать jq (или что-то еще) для сортировки их в любом порядке, чтобы исключить различия, связанные только с упорядочением элементов.Как я могу полностью сортировать JSON, используя jq?

--sort-keys решает половину проблемы, но не сортирует массивы.

Я довольно не осведомлен о jq и не знаю, как написать рекурсивный фильтр jq, который сохраняет все данные; любая помощь будет оценена по достоинству.

Я понимаю, что линейный вывод «diff» не обязательно является наилучшим способом сравнения двух сложных объектов, но в этом случае я знаю, что два файла очень похожи (почти идентичны) и линейно, line diffs отлично подходит для моих целей.

Using jq or alternative command line tools to diff JSON files отвечает на очень похожий вопрос, но не печатает различия. Кроме того, я хочу сохранить отсортированные результаты, поэтому то, что я действительно хочу, это просто программа фильтрации для сортировки JSON.

+2

Возможный дубликат [Использование JQ или альтернативные инструменты командной строки для дифф файлов в формате JSON] (http://stackoverflow.com/questions/31930041/using-jq-or-alternative-command- line-tools-to-diff-json-files) –

ответ

5

Вот решение, использующее общую функцию sorted_walk/1 (так названо по причине, описанной в приставке ниже).

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 

Пример использования Баш:

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

POSTSCRIPT: Встроенная команда определение walk/1 был пересмотрен после того, как этот ответ был впервые получен от: теперь он использует keys_unsorted а не keys.

+0

Просто то, что мне нужно, спасибо! Я вижу, что вы опубликовали вариант этого решения в соответствующем сообщении, но более простой пример здесь ответил на ряд вопросов. –

3

Я хочу разбить два текстовых файла JSON.

Использование jd с -set вариант:

Нет выхода не означает, что никакой разницы.

$ jd -set A.json B.json 

Различия показаны как путь @ и + или -.

$ jd -set A.json C.json 

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

Выходные дифференциалы могут быть также использованы в качестве заплатки с опцией -p.

$ 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

Смежные вопросы