如何在迭代值之前检查 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")' &lt;&lt;&lt; $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 中是不是存在“键”的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Unity 的 Firebase 数据库中是不是已存在键/值

在检索值之前检查哈希映射键是不是存在[重复]

如何检查Map中是不是存在键或值?

如何检查哈希中是不是存在特定键?

检查 Presto 值映射中是不是存在键

如何使用键值编码判断对象是不是存在键?