Stephen Chu
Stephen Chu

Reputation: 373

Use jq to recursively select key names of an object

I have a JSON document that looks like:

simple: 42

normal:
  description: "NORMAL"

combo:
  one:
    description: "ONE"
  two:
    description: "TWO"
  arbitrary:
    foo: 42

I want to use a jq expression to generate the following:

["normal", "one", "two"]

The condition to select the key is that its corresponding value is an object type that has a key description. In this case, keys simple and arbitrary don't qualify.

I'm having a hard time to craft the filter. Looked into with_entries and recurse/2 but can't solve it myself.

TIA.

Upvotes: 2

Views: 1865

Answers (1)

peak
peak

Reputation: 116780

It's not clear to me whether the YAML that you gave is just a "view" of your JSON or whether you actually want to start with YAML. If your document really is YAML, then one approach would be to use a tool (such as yaml2json or yq) to convert the yaml to JSON, and then run jq as shown below; another would be to use jq as a text-processor, but in that case you could just as well use awk.

yaml2json input.yaml |
  jq -c '[.. | objects | to_entries[] 
          | select(.value | has("description")?) | .key]'

Output

["normal","one","two"]

Streaming parser

This type of problem is also well-suited to jq's streaming parser, which is especially handy when dealing with very large JSON texts. Using jq --stream, a suitable jq filter would be:

[select(length==2) | .[0] | select(.[-1] == "description") | .[-2]] 

The ordering of the results will depend on the ordering of the keys produced by the YAML-to-JSON conversion tool.

Upvotes: 1

Related Questions