0

How to get the unique keys from attributes key with JQ

{"id":1, "attributes":{"a": 1, "b": 2, "c": 3}}
{"id":2, "attributes":{"a": 4, "b": 5, "d": 6}}
{"id":3, "name":"ABC"}

Result like this [ "a", "b", "c", "d" ]

I'm try like this

jq '.attributes' test.json | jq -r '[inputs | keys[]] | unique | sort'

or

jq -r '[inputs.attributes | keys[]] | unique | sort' test.json

but getting error

jq: error (at :11): null (null) has no keys

Dung Pham
  • 39
  • 4
  • Your second attempt is close. Use the `-n` option with `inputs` to also capture the first input, and use `? // {}` to streamline the case where `.attributes` is missing: `jq -n '[inputs.attributes? // null | keys[]] | unique | sort'` – pmf Sep 23 '22 at 06:24

3 Answers3

1

One way could be using reduce on subsequent inputs:

jq 'reduce inputs.attributes as $a (.attributes; . + $a) | keys'
[
  "a",
  "b",
  "c",
  "d"
]

Demo

pmf
  • 24,478
  • 2
  • 22
  • 31
0

Along the lines of your second attempt:

jq -n '[inputs.attributes // empty | keys_unsorted[]] | unique'

The important point is that we have to take care of the case where there is no "attributes" key.

Note also that unique sorts, so (unless you're using gojq) we can use keys_unsorted to avoid redundant sorting.

peak
  • 105,803
  • 17
  • 152
  • 177
  • Is there an advantage of using the null-input flag with `inputs` filter over using slurp (`-s`)? Readability? Performance? Why not `[., inputs]`? Trying to understand jq better. – knittl Sep 25 '22 at 10:39
  • Asked a new question about this: https://stackoverflow.com/q/73843868/112968 – knittl Sep 25 '22 at 10:45
0

With slurp:

jq -s 'map(.attributes|keys?)|add|unique' test.json
  • -s loads the input file as array
  • map(.attributes|keys?) extracts only the keys (ignoring errors, such as trying to get keys of null)
  • add merges all nested arrays into a single array ([[1,2],[2,3]] becomes [1,2,2,3])
  • unique sorts and removes duplicates
knittl
  • 246,190
  • 53
  • 318
  • 364