jq - jq:递归重命名键
问题描述
我的 JSON 结构如下所示。“groups”可以嵌套在“items”下任意深度,所以我需要编写一个表达式来访问每个“groups”和“items”属性(或父对象);静态路径不行。
{
"groups": [{
"name": "group1",
"items": [
{
"name": "item1",
"groups": [
{
"name": "nestedGroup1",
"items": [
{
"name": "nestedItem1",
"groups": []
},{
"name": "nestedItem2",
"groups": []
}]
}
]
},
{
"name": "item2",
"groups": []
}
]
}]
}
如何递归重命名所有“组”以将“newGroups”和“items”重命名为“newItems”?如果您将其分解,我知道我需要在每个级别创建新键并删除旧键,但我无法表达。我已经尝试了几种变化,例如
.. |= if type == "object" and has("groups") then . + { newGroups: .groups } else . end
执行第一步,但这会导致将顶级“groups”值复制到“newGroups”,同时保持嵌套“groups”不变。然后,“组”中的剩余值也得到同级“newGroups”及其嵌套“组”,没有“newGroups”同级等。
从观察来看,我的理解是算子生成的路径..
是先求值的,所以新添加的key永远不会被遍历。因此,我尝试了上述的变体,用..
带recurse
参数和不带参数的方式进行替换,认为它将获取 RHS 产生的值并将其反馈给 LHS,如下所示:
{ newGroups: .groups } | recurse |= if type == "object" and has("groups") then . + { newGroups: .groups } elif type == "object" and has("items") then . + { newItems: .items } else . end
结果更近了,但还是那么远。递归类型的作品,但仅限于已经存在的键;不会访问附加到对象的新对象。
我也尝试过弄乱paths
, getpath
, 并setpath
尝试以这种方式解决问题,但在那里也遇到了问题。请帮我解开!
解决方案
这在jq-FAQ中递归遍历使用中得到了很好的解释walk/1
。我使用了 jq-builtins 页面的标准实现walk/1
,因为我拥有的版本默认情况下没有它。
从文档中walk/1
- 递归遍历输入 JSON 实体,将每个遇到的键 , 更改k
为(k|filter)
,其中filter
是指定的过滤器,它可以是任何jq
表达式。
我在脚本中使用了以下过滤器
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys_unsorted[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
def translate_keys(f):
walk( if type == "object" then
with_entries( if .key | contains("groups") then
.key |= "newgroups"
elif .key | contains("items") then
.key |= "newitems"
else
. end
)
else
. end
);
translate_keys(.)
并将脚本运行为
jq -f script.jq json
这产生了您需要的结果。
推荐阅读
- java - 使用 ON 子句对 Collection 进行 HQL 查询
- c++ - `(i & (i + 1)) - 1` 是什么意思?(在芬威克树)
- sql - 如何处理与模式计算 SQL 的关系
- python - 使用 Telethon 获取电报用户状态
- sapui5 - 如何在 SAPUI5 中将标签和组合框组合为一个自定义控件
- python - 如何在seralizers django rest框架中过滤外键?
- python - 如何使用 CSS 和 HTML 并排放置文本和图像
- c++ - 如何在默认情况下使用非最后一个参数,以及其他非默认参数?
- javascript - 从 Promise 中解构赋值默认值
- java - 没有可可视化的 gradle 构建执行。运行 gradle build 以在 Gradle Executions View 中查看它的执行情况