用 jq 修改嵌套 JSON
Modify Nested JSON with jq
我正在尝试使用 bash/shell 脚本中的 jq <map>
函数修改嵌套的 JSON 对象;与 this blog entry 类似,但试图将此处的示例调整为嵌套对象。
返回的JSON修改如下:
{
"name": "vendor-module",
"dependencies": {
"abc": {
"from": "abc@2.4.0",
"resolved": "https://some.special.url",
"version": "2.4.0"
},
"acme": {
"from": "acme@1.2.3",
"resolved": "<CHANGE_THIS>",
"version": "1.2.3"
}
}
}
这将是我的尝试:
modules="`node -pe 'JSON.parse(process.argv[1]).dependencies.$dependency' \
"$(cat $wrapped)"`"
version="1.2.3"
resolved="some_url"
cat OLD.json |
jq 'to_entries |
map(if .dependencies[0].$module[0].from == "$module@$version"
then . + {"resolved"}={"$resolved"}
else .
end
) |
from_entries' > NEW.json
显然这行不通。当我 运行 脚本 NEW.json
被创建但没有修改或返回错误。如果我不以嵌套对象为目标(例如,"name": "vendor-module"
),脚本会按预期工作。我确定有一种方法可以使用本机 bash 和 jq..??任何帮助(通过适当的转义)将不胜感激。
更新:
感谢 的帮助,以及他使用 sponge
的建议,对我来说效果很好的解决方案是:
jq --arg mod "acme" --arg resolved "Some URL" \
'.dependencies[$mod].resolved |= $resolved' \
OLD.json | sponge OLD.json
对于您现有的示例数据,以下内容就足够了:
jq --arg mod "acme" \
--arg resolved "some_url" \
'.dependencies[$mod].resolved=$resolved' \
<in.json >out.json
...过滤 from
,相比之下:
jq --arg new_url "http://new.url/" \
--arg target "acme@1.2.3" \
'.dependencies=(.dependencies
| to_entries
| map(if(.value.from == $target)
then .value.resolved=$new_url
else . end)
| from_entries)' \
<in.json >out.json
如果您知道要更新的依赖项的名称,您可以直接对其进行索引。
$ jq --arg dep "$dep" --arg resolved "$resolved" \
'.dependencies[$dep].resolved = $resolved' \
OLD.json > NEW.json
否则,要根据名称(或其他属性)修改依赖项,搜索依赖项并更新。
$ jq --arg version "$version" --arg resolved "$resolved" \
'(.dependencies[] | select(.version == $version)).resolved = $resolved' \
OLD.json > NEW.json
我正在尝试使用 bash/shell 脚本中的 jq <map>
函数修改嵌套的 JSON 对象;与 this blog entry 类似,但试图将此处的示例调整为嵌套对象。
返回的JSON修改如下:
{
"name": "vendor-module",
"dependencies": {
"abc": {
"from": "abc@2.4.0",
"resolved": "https://some.special.url",
"version": "2.4.0"
},
"acme": {
"from": "acme@1.2.3",
"resolved": "<CHANGE_THIS>",
"version": "1.2.3"
}
}
}
这将是我的尝试:
modules="`node -pe 'JSON.parse(process.argv[1]).dependencies.$dependency' \
"$(cat $wrapped)"`"
version="1.2.3"
resolved="some_url"
cat OLD.json |
jq 'to_entries |
map(if .dependencies[0].$module[0].from == "$module@$version"
then . + {"resolved"}={"$resolved"}
else .
end
) |
from_entries' > NEW.json
显然这行不通。当我 运行 脚本 NEW.json
被创建但没有修改或返回错误。如果我不以嵌套对象为目标(例如,"name": "vendor-module"
),脚本会按预期工作。我确定有一种方法可以使用本机 bash 和 jq..??任何帮助(通过适当的转义)将不胜感激。
更新:
感谢 sponge
的建议,对我来说效果很好的解决方案是:
jq --arg mod "acme" --arg resolved "Some URL" \
'.dependencies[$mod].resolved |= $resolved' \
OLD.json | sponge OLD.json
对于您现有的示例数据,以下内容就足够了:
jq --arg mod "acme" \
--arg resolved "some_url" \
'.dependencies[$mod].resolved=$resolved' \
<in.json >out.json
...过滤 from
,相比之下:
jq --arg new_url "http://new.url/" \
--arg target "acme@1.2.3" \
'.dependencies=(.dependencies
| to_entries
| map(if(.value.from == $target)
then .value.resolved=$new_url
else . end)
| from_entries)' \
<in.json >out.json
如果您知道要更新的依赖项的名称,您可以直接对其进行索引。
$ jq --arg dep "$dep" --arg resolved "$resolved" \
'.dependencies[$dep].resolved = $resolved' \
OLD.json > NEW.json
否则,要根据名称(或其他属性)修改依赖项,搜索依赖项并更新。
$ jq --arg version "$version" --arg resolved "$resolved" \
'(.dependencies[] | select(.version == $version)).resolved = $resolved' \
OLD.json > NEW.json