jq,在任何级别上替换空值,不要碰到非空或不存在

时间:2018-07-10 19:14:20

标签: json replace jq

请协助jq的新手。 :)

我必须更新具有特定名称的字段,该名称可能会出现在JSON结构的任何级别上-可能不会。类似于下面所有JSON中的* .description字段:

{
        "a": {
                "b": [{
                                "name": "b0",
                                "description": "b0 has description"
                        },
                        {
                                "name": "b1",
                                "description": null
                        },
                        {
                                "name": "b2"
                        }
                ],
                "description": null
        },
        "s": "Some string value"
}

如果只有空值,我需要用一些伪值更新“描述”值,但是不要触摸现有值,并且不要在不存在的地方创建新字段。因此,这种情况下的预期结果是:

{
        "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被强制为“ Dummy Description”,因为这些字段存在并且为空;和.a.b [2]以及根级别保持不变,因为根本没有描述字段。

例如,如果我尝试在如下所示的已知路径上使用命令

jq '.known.level.description //= "DUMMY DESCRIPTION"' ........

它无法跳过不存在的字段,例如.a.b [2] .description;并且可以肯定,它仅适用于JSON中的已知位置。如果我尝试执行递归搜索,例如:

jq '.. | .description? //= "DUMMY DESCRIPTION"' ........

它似乎无法在数组上正常工作。

在这种情况下遍历整个JSON的正确方法是什么?谢谢!

2 个答案:

答案 0 :(得分:1)

  

在这种情况下遍历整个JSON的正确方法是什么?

答案是walk

如果您的jq还没有walk/1,则可以轻松地对其进行Google搜索(jq“ def walk”),然后在使用它之前包含其def,例如如下:

walk(if type == "object" and has("description") and .description == null
     then .description = "DUMMY DESCRIPTION"
     else . end)

答案 1 :(得分:0)

您可以考虑的一种选择是使用流。您将获得输入中每个项目的路径和值。这样,您可以查找名称为"description"的名称/值对,并更新值。

$ jq --arg replacement "DUMMY DESCRIPTION" '
fromstream(tostream | if length == 2 and .[0][-1] == "description"
    then .[1] |= (. // $replacement)
    else .
end)
' input.json