Search code examples
jsonkeyjq

jq: how to extract a value without a property name


I am trying to get values out of a json file. However, my file has a value without a property name.

The json file, names items.json, looks like this:

{
  "AQ_01_Availability": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "gAirQuality_01"
      ],
      "itemType": "Switch",
      "tags": [],
      "label": "Availability"
    }
  },
  "AQ_01_CO2": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "gAirQuality_01"
      ],
      "itemType": "Number",
      "tags": [],
      "label": "CO2"
    }
  },
  "AQ_01_Formaldehyde": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "gAirQuality_01"
      ],
      "itemType": "Number",
      "tags": [],
      "label": "Formaldehyde"
    }
  },
  "AQ_01_Humidity": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "gAirQuality_01"
      ],
      "itemType": "Number",
      "tags": [],
      "label": "Humidity",
      "category": "humidity"
    }
  }
}

I thought jq .items[0] items.json would return the name of each object; but it returns null.

My desired result would be:

AQ_01_Availability
AQ_01_CO2
AQ_01_Formaldehyde
AQ_01_Humidity

I have never used jq nor am I too familiar with json. My assumption was a well-structured file, thinking that each object starts with, say, item_name.


Solution

  • JSON has a tree-like hierarchy. The top-level (the "root") in this case is an object. Objects are a set of key-value pairs. You want to extract all keys of that top-level object. jq provides two functions that provide those keys in an array: keys and keys_unsorted. Their difference: the latter returns all the keys in the order they appeared in the input document, while the former additionally sorts that array. Either way, to get your desired output, iterate over that array using .[]. You can combine the function and the iterator to:

    jq -r 'keys_unsorted[]' items.json
    # or
    jq -r 'keys[]' items.json
    

    The --raw-output (or -r) flag converts the resulting JSON strings into raw strings.

    Demo