如何使用jq完全排序任意JSON? [英] How can I completely sort arbitrary JSON using jq?
问题描述
我想比较两个JSON文本文件.不幸的是,它们是按任意顺序构造的,因此当它们在语义上相同时,我会得到差异.我想使用jq(或其他任何一种)以任何完整的顺序对它们进行排序,以消除仅由于元素排序而引起的差异.
I want to diff two JSON text files. Unfortunately they're constructed in arbitrary order, so I get diffs when they're semantically identical. I'd like to use jq (or whatever) to sort them in any kind of full order, to eliminate differences due only to element ordering.
-sort-keys解决了一半的问题,但它不能对数组进行排序.
--sort-keys solves half the problem, but it doesn't sort arrays.
我不太了解jq,也不知道如何编写保留所有数据的jq递归过滤器;任何帮助将不胜感激.
I'm pretty ignorant of jq and don't know how to write a jq recursive filter that preserves all data; any help would be appreciated.
我意识到逐行'diff'输出不一定是比较两个复杂对象的最佳方法,但是在这种情况下,我知道这两个文件非常相似(几乎相同)并且逐行差异对我而言很好.
I realize that line-by-line 'diff' output isn't necessarily the best way to compare two complex objects, but in this case I know the two files are very similar (nearly identical) and line-by-line diffs are fine for my purposes.
使用jq或其他命令行工具来区分JSON文件可以回答一个非常相似的问题,但不会显示出差异.另外,我想保存排序后的结果,所以我真正想要的只是一个用于对JSON进行排序的过滤程序.
Using jq or alternative command line tools to diff JSON files answers a very similar question, but doesn't print the differences. Also, I want to save the sorted results, so what I really want is just a filter program to sort JSON.
推荐答案
这里是使用通用函数 sorted_walk/1 的解决方案(之所以如此命名,原因如下所述). >
Here is a solution using a generic function sorted_walk/1 (so named for the reason described in the postscript below).
normalize.jq:
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
.
POSTSCRIPT: The builtin definition of walk/1
was revised after this response was first posted: it now uses keys_unsorted
rather than keys
.
这篇关于如何使用jq完全排序任意JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!