如何使用 jq 对 json 进行分组,然后转换为 yaml
how to group json using jq and then convert to yaml
我有这个 json 我想转换。
[
{
"externalGroup": "another group admins",
"groupId": "da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
},
{
"externalGroup": "another group users",
"groupId": "7c69cac1-4a70-4170-8251-cde3762fe498"
},
{
"externalGroup": "my group admin",
"groupId": "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
},
{
"externalGroup": "my group users",
"groupId": "8370821e-edfa-4615-ac2e-47815b740f40"
},
{
"externalGroup": "some group",
"groupId": "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
},
{
"externalGroup": "some group",
"groupId": "8370821e-edfa-4615-ac2e-47815b740f40"
},
{
"externalGroup": "some group",
"groupId": "7c69cac1-4a70-4170-8251-cde3762fe498"
}
]
我试过这个,非常接近:
jq '. | group_by(.externalGroup)[] | {(.[0].externalGroup): map(.groupId)}'
我明白了:
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
]
}
{
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
{
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
]
}
{
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
]
}
{
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
但这不能正确转换为 yq。它需要看起来像这样:
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
],
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
],
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
],
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
],
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
为了得到类似的东西:
"another group admins":
- "da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
"another group users":
- "7c69cac1-4a70-4170-8251-cde3762fe498"
"my group admin":
- "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
"my group users":
- "8370821e-edfa-4615-ac2e-47815b740f40"
"some group":
- "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
- "8370821e-edfa-4615-ac2e-47815b740f40",
- "7c69cac1-4a70-4170-8251-cde3762fe498"
您缺少的部分是 from_entries
,它可以从键和值数组构建 JSON 对象。
而不是:
jq '. | group_by(.externalGroup)[] | {(.[0].externalGroup): map(.groupId)}'
尝试:
jq 'group_by(.externalGroup) | map({key:.[0].externalGroup, value:map(.groupId)}) | from_entries'
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
],
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
],
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
],
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
],
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
我做了以下修改:
- 删除了开头的
. |
,因为它没有任何改变。
- 删除了
[]
并改用 map(...)
,因为我们希望将内容保存在数组中以提供给 from_entries
。
- 我们创建
{key:..., value:...}
对以提供给 from_entries
。 ,而不是组装单条目对象
实际上,我刚刚检查了一下,发现 add
实际上比 from_entries
快一点,即使对于很长的列表也是如此。如果您使用 add
,您需要更改更少的解决方案。
jq 'group_by(.externalGroup) | map({(.[0].externalGroup):map(.groupId)}) | add'
将对象加在一起会将它们的内容组合在一起。我用 250,000 个元素的列表进行测试,它比 from_entries
稍微快一点。鉴于它也更短,而且在我看来也同样清晰,我认为它值得考虑。
- 一个值得考虑的用于生成 yaml 的替代方案是
gojq
,jq 的 Go 实现,例如
gojq --yaml-output '
group_by(.externalGroup)
| map({(.[0].externalGroup):map(.groupId)}) | add'
- 为了避免
map
的开销,您可以使用以下通用的面向流的 add
,它适用于对象或数组以及数字:
gojq --yaml-output '
def add(s): reduce s as $x (null; . + $x);
add( group_by(.externalGroup)[]
| {(.[0].externalGroup):map(.groupId)})'
我有这个 json 我想转换。
[
{
"externalGroup": "another group admins",
"groupId": "da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
},
{
"externalGroup": "another group users",
"groupId": "7c69cac1-4a70-4170-8251-cde3762fe498"
},
{
"externalGroup": "my group admin",
"groupId": "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
},
{
"externalGroup": "my group users",
"groupId": "8370821e-edfa-4615-ac2e-47815b740f40"
},
{
"externalGroup": "some group",
"groupId": "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
},
{
"externalGroup": "some group",
"groupId": "8370821e-edfa-4615-ac2e-47815b740f40"
},
{
"externalGroup": "some group",
"groupId": "7c69cac1-4a70-4170-8251-cde3762fe498"
}
]
我试过这个,非常接近:
jq '. | group_by(.externalGroup)[] | {(.[0].externalGroup): map(.groupId)}'
我明白了:
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
]
}
{
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
{
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
]
}
{
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
]
}
{
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
但这不能正确转换为 yq。它需要看起来像这样:
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
],
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
],
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
],
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
],
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
为了得到类似的东西:
"another group admins":
- "da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
"another group users":
- "7c69cac1-4a70-4170-8251-cde3762fe498"
"my group admin":
- "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
"my group users":
- "8370821e-edfa-4615-ac2e-47815b740f40"
"some group":
- "e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
- "8370821e-edfa-4615-ac2e-47815b740f40",
- "7c69cac1-4a70-4170-8251-cde3762fe498"
您缺少的部分是 from_entries
,它可以从键和值数组构建 JSON 对象。
而不是:
jq '. | group_by(.externalGroup)[] | {(.[0].externalGroup): map(.groupId)}'
尝试:
jq 'group_by(.externalGroup) | map({key:.[0].externalGroup, value:map(.groupId)}) | from_entries'
{
"another group admins": [
"da2e42c8-6423-4d32-99b5-5fc58f9f80b8"
],
"another group users": [
"7c69cac1-4a70-4170-8251-cde3762fe498"
],
"my group admin": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a"
],
"my group users": [
"8370821e-edfa-4615-ac2e-47815b740f40"
],
"some group": [
"e08a1d9d-f108-4e87-bdb3-ee4f10c6752a",
"8370821e-edfa-4615-ac2e-47815b740f40",
"7c69cac1-4a70-4170-8251-cde3762fe498"
]
}
我做了以下修改:
- 删除了开头的
. |
,因为它没有任何改变。 - 删除了
[]
并改用map(...)
,因为我们希望将内容保存在数组中以提供给from_entries
。 - 我们创建
{key:..., value:...}
对以提供给from_entries
。 ,而不是组装单条目对象
实际上,我刚刚检查了一下,发现 add
实际上比 from_entries
快一点,即使对于很长的列表也是如此。如果您使用 add
,您需要更改更少的解决方案。
jq 'group_by(.externalGroup) | map({(.[0].externalGroup):map(.groupId)}) | add'
将对象加在一起会将它们的内容组合在一起。我用 250,000 个元素的列表进行测试,它比 from_entries
稍微快一点。鉴于它也更短,而且在我看来也同样清晰,我认为它值得考虑。
- 一个值得考虑的用于生成 yaml 的替代方案是
gojq
,jq 的 Go 实现,例如
gojq --yaml-output '
group_by(.externalGroup)
| map({(.[0].externalGroup):map(.groupId)}) | add'
- 为了避免
map
的开销,您可以使用以下通用的面向流的add
,它适用于对象或数组以及数字:
gojq --yaml-output '
def add(s): reduce s as $x (null; . + $x);
add( group_by(.externalGroup)[]
| {(.[0].externalGroup):map(.groupId)})'