如何在迭代值之前检查 jq 中是不是存在“键”
Posted
技术标签:
【中文标题】如何在迭代值之前检查 jq 中是不是存在“键”【英文标题】:How to check for presence of 'key' in jq before iterating over the values如何在迭代值之前检查 jq 中是否存在“键” 【发布时间】:2017-06-25 03:26:39 【问题描述】:我从下面的查询中得到Cannot iterate over null (null)
,因为.property_history
不存在于result
对象中。
在继续使用map(...)
之前,如何检查.property_history
密钥是否存在?
我尝试使用类似sold_year= `echo "$content" | jq 'if has("property_history") then
map(select(.event_name == "Sold"))[0].date' else null end
的东西
原始查询:
sold_year=`echo "$content" | jq '.result.property_history | map(select(.event_name == "Sold"))[0].date'`
JSON:
"result":
"property_history":[
"date":"01/27/2016",
"price_changed":0,
"price":899750,
"event_name":"Listed",
"sqft":0
,
"date":"12/15/2015",
"price_changed":0,
"price":899750,
"event_name":"Listed",
"sqft":2357
,
"date":"08/30/2004",
"price_changed":0,
"price":739000,
"event_name":"Sold",
"sqft":2357
]
【问题讨论】:
【参考方案1】:您可以使用jq
中的select-expression 来完成您想要实现的目标,例如,
jq '.result
| select(.property_history != null)
| .property_history
| map(select(.event_name == "Sold"))[0].date'
【讨论】:
select(.property_history != null) 是多余的,可以简单写成:select(.property_history) @icenac - 这两个表达式不等价。当心! @peak 我知道,但对于这个特定的例子,它们是【参考方案2】:从技术上讲,要测试属性是否存在,您应该使用has/1
,但在目前的情况下,使用后缀?
运算符可能会更好,例如:
$ jq '.result
| .property_history[]?
| select(.event_name == "Sold")
| .date'
"08/30/2004"
【讨论】:
酷。我试过了......但它给了boolean
。看起来技巧是.[]
您可以将其缩短为jq '.result.property_history[]? | select(.event_name == "Sold") | .date'
这比公认的答案要紧凑得多。
当property_history
不存在时,此答案会导致错误。奥拉夫评论中的缩短版本确实有效。【参考方案3】:
使用has("mykey1")
(用于对象)或has(0)
(用于数组):
jq 'has("name")' <<< "\"name\": \"hello\""
输出:
true
【讨论】:
if [ "$( jq 'has("alert")' <<< $this_alert_json )" == "true" ]; then
整洁。简洁明了。 +1
对于 POSIX shell(无重定向功能):echo "\"name\": \"hello\"" | jq 'has("name")'
如果您不确定传入的字符串是有效的 JSON:echo "\"name\": \"hello\"" | jq -R 'fromjson? | has("name")'
如果这是您想要的,这不会为错误的 JSON 引发错误【参考方案4】:
诀窍是将// 与empty 一起使用:
jq '.result.property_history // empty | map(select(.event_name == "Sold"))[0:1][].date'
另一种选择是使用额外的选择:
jq '.result.property_history | select(.) | map(select(.event_name == "Sold"))[0:1][].date'
【讨论】:
【参考方案5】:一般模式:
try (...) // "default_value"
按照你的逻辑:
jq 'try (.result.property_history | map(select(.event_name == "Sold"))[0].date) // "default_value"'
try
(没有捕获)如果表达式失败则返回空。 //
如果值为空,则提供默认值。
【讨论】:
以上是关于如何在迭代值之前检查 jq 中是不是存在“键”的主要内容,如果未能解决你的问题,请参考以下文章