Cannot index string with string "foo"

Viewed 1406

I have some json (included below), and the first key is a random number (a docker image ID), so I won't know what it is before I have to parse the json.

what I would like to do is

cat eval.json | jq \
'."3193328829c7b3ec6be0ab6bfd8988b97a35006ea578c9ce4ab7fe29cbc5ec94".result.rows[] | select (.[2]=="stop")'

This works fine, except I need to do this in the general case where I don't know the Image ID ahead of time.

I tried this, which sort of works except I get some "cannot index" errors:

cat eval.json | jq .[] | jq '.result.rows[] | select (.[2]=="stop")'
[
  "CVE-2021-3156+sudo",
  "HIGH Vulnerability found in os package type (dpkg) - sudo (fixed in: 1.8.31-1ubuntu1.2)(CVE-2021-3156 - http://people.ubuntu.com/~ubuntu-security/cve/CVE-2021-3156)",
  "stop",
  false
]
jq: error (at <stdin>:33): Cannot index array with string "result"
jq: error (at <stdin>:34): Cannot index string with string "result"
jq: error (at <stdin>:35): Cannot index array with string "result"
jq: error (at <stdin>:36): Cannot index array with string "result"

a little refinement helped with the array issues, but I still have the string error:

cat eval.json | jq '.[].result.rows[] | select (.[2]=="stop")'
[
  "CVE-2021-3156+sudo",
  "HIGH Vulnerability found in os package type (dpkg) - sudo (fixed in: 1.8.31-1ubuntu1.2)(CVE-2021-3156 - http://people.ubuntu.com/~ubuntu-security/cve/CVE-2021-3156)",
  "stop",
  false
]
jq: error (at <stdin>:38): Cannot index array with string "result"

I can delete those last four keys (I don't think I'll ever need them for what I'm trying to do), but that seems like a pretty clunky hack.

cat eval.json | jq 'del(.whitelist_names, .whitelist_data, .policy_name, .policy_data) |  .[].result.rows[] | select ((.[2]=="stop") and (.[3]==false)) | .[0], .[1]'
"CVE-2021-3156+sudo"
"HIGH Vulnerability found in os package type (dpkg) - sudo (fixed in: 1.8.31-1ubuntu1.2)(CVE-2021-3156 - http://people.ubuntu.com/~ubuntu-security/cve/CVE-2021-3156)"

Is there something better than using del to clear those keys out? it seems like if there were some way to specify the first key like there is for the Nth element in an array, that would be a lot easier. The other think I thought about was doing something awkward like just printing the keys out, capturing that long string in a variable, then using that to select that key directly, but that is more cumbersome than deleting the other keys.

full json below:

{
  "3193328829c7b3ec6be0ab6bfd8988b97a35006ea578c9ce4ab7fe29cbc5ec94": {
    "result": {
      "final_action": "stop",
      "header": [
        "Trigger_Id",
        "Check_Output",
        "Gate_Action",
        "Whitelisted"
      ],
      "row_count": 3,
      "rows": [
        [
          "41cb7cdf04850e33a11f80c42bf660b3",
          "Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check",
          "warn",
          false
        ],
        [
          "CVE-2018-20839+libudev1",
          "MEDIUM Vulnerability found in os package type (dpkg) - libudev1 (CVE-2018-20839 - http://people.ubuntu.com/~ubuntu-security/cve/CVE-2018-20839)",
          "warn",
          false
        ],
        [
          "CVE-2021-3156+sudo",
          "HIGH Vulnerability found in os package type (dpkg) - sudo (fixed in: 1.8.31-1ubuntu1.2)(CVE-2021-3156 - http://people.ubuntu.com/~ubuntu-security/cve/CVE-2021-3156)",
          "stop",
          false
        ]
      ]
    }
  },
  "policy_data": [],
  "policy_name": "",
  "whitelist_data": [],
  "whitelist_names": []
}
1 Answers

Adding one or more "?" would be one way to resolve the issue:


.[].result?.rows[] | select (.[2]=="stop")

If you want to specify the first key, use keys_unsorted[0], as in:

.[keys_unsorted[0]].result.rows[] | select (.[2]=="stop")
Related