请协助jq.中的新手:(
我必须更新一个具有特定名称的字段,该字段可能出现在任何级别的JSON结构上,也可能不会。与下面JSON中的所有*.description字段类似:
{
"a": {
"b": [{
"name": "b0",
"description": "b0 has description"
},
{
"name": "b1",
"description": null
},
{
"name": "b2"
}
],
"description": null
},
"s": "Some string value"
}
我需要用一些伪值更新"描述"值,如果它只有null值,但不要接触现有值,也不要在不存在的地方创建新字段。因此,在这种情况下,期望的结果是:
{
"a": {
"b": [{
"name": "b0",
"description": "b0 has description"
},
{
"name": "b1",
"description": "DUMMY DESCRIPTION"
},
{
"name": "b2"
}
],
"description": "DUMMY DESCRIPTION"
},
"s": "Some string value"
}
在这里,.a.b[0].description保持不变,因为它存在并且不是null。a.b[1].description和.a.description被强制为"假人描述",因为这些字段存在并且为空;和.a.b[2]以及根级别保持不变,因为根本没有描述字段。
例如,如果我尝试在已知路径上使用命令,如下面的
jq '.known.level.description //= "DUMMY DESCRIPTION"' ........
它无法跳过.a.b[2].description等不存在的字段;当然,它只适用于JSON中的已知位置。如果我尝试做递归搜索,比如:
jq '.. | .description? //= "DUMMY DESCRIPTION"' ........
它似乎无法在数组上正常工作。
在这种情况下,遍历整个JSON的正确方法是什么?谢谢
在这种情况下,遍历整个JSON的正确方法是什么?
答案是walk
!
如果你的jq还没有walk/1
,你可以很容易地在谷歌上搜索它(jq"defwalk"(,然后在使用它之前包括它的def,例如:
walk(if type == "object" and has("description") and .description == null
then .description = "DUMMY DESCRIPTION"
else . end)
您可以考虑的一个选项是使用流。您将获得输入中每个项目的路径和值。这样,您就可以查找名称为"description"
的名称/值对并更新值。
$ jq --arg replacement "DUMMY DESCRIPTION" '
fromstream(tostream | if length == 2 and .[0][-1] == "description"
then .[1] |= (. // $replacement)
else .
end)
' input.json