有没有一种方法可以在jq的对象构造中使用默认值?

时间:2019-08-19 02:44:00

标签: json jq default-value

我想根据条件从数组中过滤并分配一个值,如果数组没有匹配的对象,则使用默认值。

这是一个示例对象:

{
    "array" : [
            {   
                "id": "A",
                "conversations": [   
                    {
                    "conversation": "1",
                    "type": "good"
                    },
                    {
                    "conversation": "2", 
                    "type": "bad"
                    }
                ]

            },
            {   
                "id": "B",
                "conversations": [   
                    {
                    "conversation": "3",
                    "type": "good"
                    },
                    {
                    "conversation": "4", 
                    "type": "bad"
                    }
                ]

            },
            {   
                "id": "C",
                "conversations": [   
                    {
                    "conversation": "5",
                    "type": "bad"
                    },
                    {
                    "conversation": "6", 
                    "type": "bad"
                    }
                ]

            }
        ]
}

必填输出:

{
  "id": "A",
  "goodConversation": "1"
}
{
  "id": "B",
  "goodConversation": "3"
},
{
  "id": "C",
  "goodConversation": null
}

输入的回声:

echo '{"array":[{"id":"A","conversations":[{"conversation":"1","type":"good"},{"conversation":"2","type":"bad"}]},{"id":"B","conversations":[{"conversation":"3","type":"good"},{"conversation":"4","type":"bad"}]},{"id":"C","conversations":[{"conversation":"5","type":"bad"},{"conversation":"6","type":"bad"}]}]}'

我尝试按照jq

运行
jq '.array[] | {id, "goodConversation": .conversations[] | select(.type == "good") | .conversation}'

实际输出:

{
  "id": "A",
  "goodConversation": "1"
}
{
  "id": "B",
  "goodConversation": "3"
}

由于ID为“ C”的对象之间没有良好的对话,因此整个对象被过滤掉了。有没有一种方法可以创建包含null作为值的“ C”的输出对象?

说明

  • “对话”最多只能有一个良好的对话。
  • 我正在使用jq 1.5

2 个答案:

答案 0 :(得分:1)

提供默认值的一种方法通常是使用//“替代”运算符。在您奠定的基础上,您可以编写:

.array[]
| {id, 
   "goodConversation": 
     ((.conversations[]
      | select(.type == "good")
      | .conversation) // null) }

但是,如果有多个“良好”对话,则可能不是您想要的。如果不是,请考虑使用first,例如:

.array[]
| {id,
   "goodConversation":
     ( first(.conversations[]
             | select(.type == "good")
             | .conversation) // null)}

答案 1 :(得分:0)

问题是特定于jq的,但是问的类型有一个常见的JSON操作任务,或者可以使用walk-path Unix实用程序 {{3 }}

bash $ <sample.json jtc -w'<C:null>f[id]:<I>a:[-1][type]:<"good">j[-1][conversation]<C>v' -T'{"id": {{I}}, "goodConversation": {{C}} }' -j
[
   {
      "goodConversation": "1",
      "id": "A"
   },
   {
      "goodConversation": "3",
      "id": "B"
   },
   {
      "goodConversation": null,
      "id": "C"
   }
]
bash $ 

walk-path-w)的阐述:

  • <C:null>f-将在变量null中设置默认C,否则将进一步失败
  • [id]:<I>a-递归地在变量I中查找并存储标签id的值
  • [-1][type]:<"good">j-从找到的id开始执行一次,查找/匹配json字符串"type": "good"
  • [-1][conversation]<C>v然后从找到的字符串,地址conversation开始一次,并将其值存储在变量C

每次步行结束时,变量IC将收集各自的值,并将其插值到模板(-T)中,以产生所需的结果

PS>披露:我是jtc-用于JSON操作的shell cli工具的创建者