Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jq to list keys in a JSON object

I have a hierarchically deep JSON object created by a scientific instrument, so the file is somewhat large (1.3MB) and not readily readable by people. I would like to get a list of keys, up to a certain depth, for the JSON object. For example, given an input object like this

{
    "acquisition_parameters": {
        "laser": {
            "wavelength": {
                "value": 632,
                "units": "nm"
            }
        },
        "date": "02/03/2525",
        "camera": {}
    },
    "software": {
        "repo": "github.com/username/repo",
        "commit": "a7642f",
        "branch": "develop"
    },
    "data": [{},{},{}]
}

I would like an output like such.

{
    "acquisition_parameters": [
        "laser",
        "date",
        "camera"
    ],
    "software": [
        "repo",
        "commit",
        "branch"
    ]
}

This is mainly for the purpose of being able to enumerate what is in a JSON object. After processing the JSON objects from the instrument begin to diverge: for example, some may have a field like .frame.cross_section.stats.fwhm, while others may have .sample.species, so it would be convenient to be able to interrogate the JSON object on the command line.

like image 739
Ryan Avatar asked Sep 24 '13 02:09

Ryan


3 Answers

The following should do exactly what you want

jq '[(keys - ["data"])[] as $key | { ($key): .[$key] | keys }] | add'

This will give the following output, using the input you described above:

{
  "acquisition_parameters": [
    "camera",
    "date",
    "laser"
  ],
  "software": [
    "branch",
    "commit",
    "repo"
  ]
}
like image 148
mwag Avatar answered Oct 17 '22 00:10

mwag


Given your purpose you might have an easier time using the paths builtin to list all the paths in the input and then truncate at the desired depth:

$  echo '{"a":{"b":{"c":{"d":true}}}}' | jq -c '[paths|.[0:2]]|unique'
[["a"],["a","b"]]
like image 20
user2259432 Avatar answered Oct 17 '22 00:10

user2259432


Here is another variation uing reduce and setpath which assumes you have a specific set of top-level keys you want to examine:

  . as $v
| reduce ("acquisition_parameters", "software") as $k (
     {}; setpath([$k]; $v[$k] | keys)
  )
like image 36
jq170727 Avatar answered Oct 16 '22 22:10

jq170727