使用jq有条件地修改对象属性

时间:2016-09-04 19:47:50

标签: json shell command-line jq

我有这个JSON示例:

[
    {
        "name": "val1",
        "expire": { "$value": 10 }
    },
    {
        "name": "val2",
        "expire": 20
    },
    {
        "name": "val3"
    }
]

我想用jq:

将其转换为这种形式
[
    {
        "name": "val1",
        "expire": 10
    },
    {
        "name": "val2",
        "expire": 20
    },
    {
        "name": "val3",
        "expire": null
    }
]

所有我发现它的if-then-else,但看起来我不知道如何建立正确的表达。

基于类型检查的条件,它看起来是正确的方式,但只是返回"编译" - 时间错误,我不知道如何解决它:

.[] | { name, expire: (if .expire then (if type(.expire) == "number" then .expire else .expire."$value" end) else null end) }

基于"$value"检查的条件,以某种方式过滤掉第二个对象:

.[] | { name, expire: (if .expire then (if .expire."$value"? then .expire."$value" else .expire end) else null end) }

根据我的理解,这里的问题是在内部if,其中使用.expire."$value"?检查第二个对象时,由于错误而抛出错误并从结果中删除了对象。

2 个答案:

答案 0 :(得分:3)

您可以通过另一种方式来考虑使用expire(如果存在)或当前值更新每个对象的"$value"属性。如果该值不存在,则只需null

.[].expire |= (."$value"? // .)

答案 1 :(得分:2)

试试这个过滤器:

map( {name, 
      "expire": (.expire | if type == "object" then .["$value"] elif type == "number" then . else null end) } )

或(在边缘情况下具有显着不同的语义):

map(.expire |= if type == "object" then .["$value"]
               elif type == "number" then . else null end)