Home > Enterprise >  jq, getting an unknown parent node after finding it with one of its children value
jq, getting an unknown parent node after finding it with one of its children value

Time:10-12

I have a complex (at least for me) issue with jq, and this structure :

{
  "os": {
    "ubuntu": {
      "16.04": {
        "codename": "xenial",
        "bootstrap": "preseed",
        "guest_type": "ubuntu64Guest",
        "iso_name": "ubuntu-16.04.7-server-amd64.iso",
        "iso_checksum": "9bb30a2ea6466b0c02aacfa96f6e3516",
      },
      "18.04": {
        "codename": "bionic",
        "bootstrap": "preseed",
        "guest_type": "ubuntu64Guest",
        "iso_name": "ubuntu-18.04.2-server-amd64.iso",
        "iso_checksum": "34416ff83179728d54583bf3f18d42d2",
        "arm": {
          "iso_name": "ubuntu-18.04.5-server-arm64.iso",
          "iso_checksum": "5056eaf87425b550376e6733b05de6e9"
        }
      }
    },
    "rhel": {
      "7.4": {
        "codename": "maipo",
        "bootstrap": "kickstart",
        "guest_type": "rhel7_64Guest",
        "iso_name": "rhel-server-7.4-x86_64-boot.iso",
        "iso_checksum": "94ad0929b79b5d13b33acafc8da8d364",
      },
      "7.6": {
        "codename": "maipo",
        "bootstrap": "kickstart",
        "guest_type": "rhel7_64Guest",
        "iso_name": "rhel-server-7.6-x86_64-boot.iso",
        "iso_checksum": "4a611d2bbfa6912eada91096af14ec84",
      }
    }
  }
}

I need to get the "ubuntu" node content by searching it with "18.04", without knowing the "ubuntu" node key name. So if i search the children node named "7.4", it should identify its parent as "rhel" and returns it.

Basically, with an os version, i should get the os name, but i have no way of knowing the os name beforehand.

I tried a few commands (didn't keep them sorry), with the help of this cheatsheet, without luck : https://gist.github.com/olih/f7437fb6962fb3ee9fe95bda8d2c8fa4

It is even possible ?

Thanks.

CodePudding user response:

You can use has to check for keys:

jq '.os | .[] |= select(has("18.04"))'
{
  "ubuntu": {
    "16.04": {
      "codename": "xenial",
      "bootstrap": "preseed",
      "guest_type": "ubuntu64Guest",
      "iso_name": "ubuntu-16.04.7-server-amd64.iso",
      "iso_checksum": "9bb30a2ea6466b0c02aacfa96f6e3516"
    },
    "18.04": {
      "codename": "bionic",
      "bootstrap": "preseed",
      "guest_type": "ubuntu64Guest",
      "iso_name": "ubuntu-18.04.2-server-amd64.iso",
      "iso_checksum": "34416ff83179728d54583bf3f18d42d2",
      "arm": {
        "iso_name": "ubuntu-18.04.5-server-arm64.iso",
        "iso_checksum": "5056eaf87425b550376e6733b05de6e9"
      }
    }
  }
}

Demo

CodePudding user response:

Basically, with an os version, i should get the os name, but i have no way of knowing the os name beforehand.

You can use to_entires() with select() to filter on the key. Then return it parent's key to get the OS name:

.os | to_entries[] | select(.value | has("18.04")).key
// "ubuntu"

.os | to_entries[] | select(.value | has("7.6")).key
// "rhel"

JqPlay Demo

  • Related