Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce a list of all unique key path from a given JSON

I would like to produce a list of all unique key path from a given JSON, each one in a line.

For example, from this input JSON:

{
   "results":[
      {
         "id":306,
         "name":"First Company",
         "branches":[
            {
               "id":4191,
               "city":"San Francisco",
               "customers":[
                  {
                     "id":446,
                     "name":"Big Tech 1"
                  },
                  {
                     "id":447,
                     "name":"Big Tech 2"
                  }
               ]
            },
            {
               "id":4192,
               "city":"Miami",
               "customers":[
                  {
                     "id":448,
                     "name":"Insurance Tech 1"
                  },
                  {
                     "id":449,
                     "name":"Health Tech 2"
                  }
               ]
            }
         ]
      }
   ]
}

I would like to produce this output:

  results
  results.id
  results.name
  results.branches
  results.branches.id
  results.branches.city
  results.branches.customers
  results.branches.customers.id
  results.branches.customers.name

I am struggling with the command line below but it is not working.

jq '
def path(k):
  if k | type == "object":
    reduce(.keys[] | path(.), k)
  else:
    [k]
;

.[] | path(".") | flatten | sort' example.json

Any help, please?

like image 306
Denio Mariz Avatar asked Dec 12 '25 16:12

Denio Mariz


2 Answers

You could map the paths to only contain strings, then drop the duplicates using unique, and join the items by providing a delimiter:

jq -r '[paths | map(strings)] | unique[] | join(".")'
results
results.branches
results.branches.city
results.branches.customers
results.branches.customers.id
results.branches.customers.name
results.branches.id
results.id
results.name

Demo

To retain the document order (unique also sorts the array), you could deduplicate the list by using the joined paths as (unique-by-definition) object fields instead:

jq -r '[paths | map(strings) | join(".") | {(.):.}] | add[]'
results
results.id
results.name
results.branches
results.branches.id
results.branches.city
results.branches.customers
results.branches.customers.id
results.branches.customers.name

Demo

like image 140
pmf Avatar answered Dec 14 '25 04:12

pmf


With paths function, filtering out array indices of object keys and collecting unique paths:

jq '[paths(.) | map(select(type != "number")) | join(".")] | unique[]' test.json 

"results"
"results.branches"
"results.branches.city"
"results.branches.customers"
"results.branches.customers.id"
"results.branches.customers.name"
"results.branches.id"
"results.id"
"results.name"
like image 30
RomanPerekhrest Avatar answered Dec 14 '25 05:12

RomanPerekhrest



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!