Как я могу полностью отсортировать произвольный JSON с помощью jq?

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

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

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

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

Использование jq или альтернативных инструментов командной строки для сравнения файлов JSON отвечает на очень похожий вопрос, но не печатает различия. Кроме того, я хочу сохранить отсортированные результаты, так что мне действительно нужна программа-фильтр для сортировки JSON.

Ответы на вопрос(2)

Решение Вопроса

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

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

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

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

 Jeff Learman08 июл. 2016 г., 18:24
Только то, что мне было нужно, спасибо! Я вижу, вы опубликовали вариант этого решения в соответствующем сообщении, но более простой пример здесь ответил на ряд вопросов.

использование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

Ваш ответ на вопрос