jq以不同的方式对KEY和VALUES进行排序 - 如何以相同的顺序枚举它们?

Ezh*_*gam 7 unix shell json enumeration jq

我使用curl命令以JSON格式获得REST输出,如下所示

使用以下方法获取KEY名称:

curl http://test.te:8080/testApp/app/version | jq '.version' | jq '. | keys'
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

"Archiver-Version",
"Build-Id",
"Build-Jdk",
"Build-Number",
"Build-Tag",
"Built-By"
Run Code Online (Sandbox Code Playgroud)

单独使用VALUES:

curl http://test.te.com:8080/testApp/app/version | jq '.version' | jq '.[]'
Run Code Online (Sandbox Code Playgroud)

OUTPUT(注意值的顺序与键名的顺序不对应;例如,第一个值"user@test.com",是键的值"Built-By",而不是如我所料,第一个键,"Archiver-Version"):

"user@test.com"
"1634d38"
"sandbox"
"02-03-2014-13:41"
"testApp"
Run Code Online (Sandbox Code Playgroud)

我试图将KEYS和VALUES分配给单独的数组,以便我可以迭代它们并以表格格式显示它们.

但是这两个命令以不同的方式排序,我无法直接分配值和键.

有没有改变KEYS和VALUES的排序,以便两者相同?

小智 8

jq有一个对键进行排序的选项.见http://stedolan.github.io/jq/manual/#Invokingjq

--sort-keys / -S:

Output the fields of each object with the keys in sorted order.
Run Code Online (Sandbox Code Playgroud)

然而,当前发布的jq版本(1.3)尚未进行此增强,您需要通过其主分支的最新代码编译jq.请参阅http://stedolan.github.io/jq/download/,"Linux或OS X上的源代码"部分.

有关此功能的完整历史记录和详细信息,请参阅问题#79"按名称对对象成员进行排序的选项或功能" https://github.com/stedolan/jq/issues/79


mkl*_*nt0 6

问题源于jq可能令人惊讶的默认行为:

  • keys按字母顺序排列键.
  • .[]根据键的输入顺序枚举值[1]

换句话说:如果您在一次传递中使用keys提取对象的,然后在另一次传递.[]中提取其,则相应的输出元素可能不匹配.

jqv1.5引入了该keys_unsorted/0功能,它提供了一个简单的解决方案:

# Sample input with unordered keys.
# Sorting the values results in the same order as sorting the keys,
# so the output order of values below implies the key enumeration order that was applied.
json='{ "c":3, "a":1, "b":2 }'
Run Code Online (Sandbox Code Playgroud)

按输入顺序打印,使用keys_unsorted/0:

$ echo "$json" | jq -r 'keys_unsorted[]'
c
a
b
Run Code Online (Sandbox Code Playgroud)

按输入顺序打印,这些[]总是如下:

$ echo "$json" | jq -r '.[]'
3
1
2
Run Code Online (Sandbox Code Playgroud)

警告:直到版本v1.3,使用.[]导致没有保证的枚举顺序(使用了底层哈希表的键排序,这是一个实现细节); 如果您仍然必须使用v1.3,则可以使用to_entries下面显示的方法.


[v1.3 +] to_entries/0,在user2259432的有用答案中使用,也按输入顺序枚举属性:

# Extract keys
$ echo "$json" | jq -r 'to_entries | map(.key)[]'
c
a
b
Run Code Online (Sandbox Code Playgroud)
# Extract values
$ echo "$json" | jq -r 'to_entries | map(.value)[]'
3
1
2
Run Code Online (Sandbox Code Playgroud)

警告:在v1.5之前,to_entries/0按键排序输出键值对.

但是,由于to_entries/0可以用于枚举键和值,因此即使在v1.5之前的版本中,它仍然是在并行键/值提取中生成稳定枚举顺序的可行解决方案.


[V1.3 +]如果相反,你要在枚举排序按按键顺序:

按字母顺序排序打印,使用keys/0:

$ echo "$json" | jq -r 'keys[]'
a
b
c
Run Code Online (Sandbox Code Playgroud)

按字母顺序排序的键打印:

$ echo "$json" | jq -r 'keys[] as $k | .[$k]'
1
2
3
Run Code Online (Sandbox Code Playgroud)

一个需要注意的重-S/--sort-keys:

此选项仅适用于输出上的整个对象:

$ echo "$json" | jq -Sc '.'
{"a":1,"b":2,"c":3}  # Sorted by key
Run Code Online (Sandbox Code Playgroud)

当您使用运算符或函数访问对象的内部时,不适用:

$ echo "$json" | jq -S '.[]' # !! -S doesn't apply, because [] always uses input order
3
1
2
Run Code Online (Sandbox Code Playgroud)

[1]在v1.5之前,没有保证特定的顺序,导致同样的问题.


小智 5

你也可以

$ echo '{"a":0, "b":1}' | jq -c 'to_entries|map([.key, .value])|map(.[])'
["a",0,"b",1]
Run Code Online (Sandbox Code Playgroud)