【问题标题】:Verifying existence of a root level element with jq使用 jq 验证根级元素的存在
【发布时间】:2020-01-22 14:05:03
【问题描述】:

给定如下 JSON 结构,我想测试 sys/ 顶级键是否存在。

{                                                                                                                                                             
  "abc/": {                                                                                                                                             
    "uuid": "fd"
   },
 "sys/": {                                                                                                                                                   
    "uuid": "id2"
  }
}

我尝试了各种构造,例如 jq "sys/"jq "sys/.uuid",但出现编译错误和/或错误,例如“jq: error: sys/0 is not defined at , line 1:”

请注意,来自jq 的结果代码 ($?) 正确返回以反映实际结果非常重要(因为这是在配置管理测试中使用的)。

【问题讨论】:

    标签: json bash jq


    【解决方案1】:

    您只需要使用has 属性,它会根据所提到的键的存在返回一个布尔值

    jq 'has("sys/")'
    

    请注意,您可以自定义jq 以返回布尔字符串甚至null,但它们都不能直接用于仅使用退出代码01 的shell 条件。

    如果您希望 jq 的结果用于 shell 条件语句,您可以使其返回退出代码。有一个选项支持这一点。来自文档

    -e / --exit-status:

    如果最后一个输出值既不是false 也不是null,则将jq 的退出状态设置为0,如果最后一个输出值是falsenull,则1,或@ 987654336@ 如果没有产生有效结果。

    所以在给定的 JSON 上使用它

    jq -e 'has("sys/")' json > /dev/null
    echo $?
    0
    

    但对于不存在的密钥 sys1,它会发出

    jq -e 'has("sys1/")' json > /dev/null
    echo $?
    1
    

    请注意,> /dev/null 会抑制应用过滤器时抛出的标准输出,即布尔字符串值。如果您的 jq 版本不支持该选项,或者您正在寻找替代方法来执行此操作,您可以直接匹配从 has() 过滤器返回的字符串,而不是评估退出代码,即

    if [ $(jq 'has("sys/")' json) = "true" ]; then
        printf '%s\n' 'key present'
    fi
    

    【讨论】:

    • 这两个答案看起来都很棒。我唯一的问题是jq 的返回码在两者上都是 true (0)。例如jq 'has("nonexistent/")'$? = 0
    • @LittleCode:OP 中没有,你能添加一个你想在条件中使用它的注释
    • 完成。我会假设像has() 这样的东西无论如何都会在返回代码中反映真/假。
    【解决方案2】:

    添加到之前的答案,这是在 Python 3 中执行此操作的方法,以防有人无法安装 jq

    #!/usr/local/bin/python3
    
    import json
    
    obj=json.loads("""{                                               
      "abc/": {                                                              
        "uuid": "fd"
       },
     "sys/": {                                                                
        "uuid": "id2"
      }
    }""")
    
    if 'sys/' in obj:
        exit(0)
    else :
        exit(1)
    

    【讨论】:

    • 您无需为实际要求的问题添加任意选择的替代方案的答案。
    • @chepner - 恕我直言,这种态度降低了 SO 的价值,因为 SO 不仅存在于人们提出问题的范围内,而且存在于整个范围内,包括那些可能感兴趣的人,甚至是替代方案之后的人解决方案。
    • 实际上,对于定义明确、重点的问题,SO 是精确的。 OP 没有要求 Python 解决方案;他们没有要求 Perl、Ruby、C、Haskell、R、Prolog 或 Scheme 解决方案。他们要求jq 解决方案。如果您认为回答 Python 的问题是可行的,您可以发布您的 自己的 自我回答的问题。但不要随意扩大现有问题的范围。
    • @chepner: SO is precisely for answers to well-defined, focused questions - 需要引用。对于最合适的答案,SO(准确地说是 SE)提供了一个投票系统。以下是替代解决方案的反驳论点:meta.stackoverflow.com/questions/300254/…
    • 如果您认为允许将每个问题都视为邀请以任何可以想象的语言提供解决方案的问题,那么我在这里没有什么好说的了。
    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 2014-01-10
    • 2016-07-04
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多