How can I map items together in a json structure with jq? How can I map items together in a json structure with jq? json json

How can I map items together in a json structure with jq?


This looks like a overkill to me but it does the job.

[path(.[][][].item) as $p | [$p, getpath($p)]] |group_by( .[1] ) |map({(.[0][1]): (. | map([.[0][0,1]]))})|add

Save the above jq filter in file item_in.jq and run it as jq --from-file item_in.jq. Passing your input to this gives the following output:

{  "beer": [    [      "lorry1",      "box2"    ],    [      "lorry2",      "box2"    ]  ],  "potatoes": [    [      "lorry1",      "box2"    ]  ],  "shoes": [    [      "lorry1",      "box1"    ],    [      "lorry2",      "box1"    ]  ],  "snacks": [    [      "lorry1",      "box1"    ],    [      "lorry2",      "box1"    ]  ]}

The initial transformation was to dump leaves and their paths from the input JSON tree.Seehttps://github.com/stedolan/jq/issues/78#issuecomment-17819519


The answer I'd like to get is lorry1, box1 and lorry2, box1

In this case, you can get it with:

path(.. | select(.item? == "shoes"))

Which returns:

["lorry1","box1",0]["lorry2","box1",0]

These are the paths in your object that will lead to an object which .item property is set to "shoes"


Here's a generic solution that does not assume the "items" are in arrays, or even that the values associated with the "item" keys are always strings:

jq -c '. as $in  | [paths as $p | select($p[-1] == "item") | $p]  | group_by(. as $p | $in|getpath($p))  | .[]  | (.[0] as $p | $in | getpath($p)) as $v  | {($v|tostring):  ( map(.[:-1] | if .[-1] | type == "number" then .[:-1] else . end)) }'

Output

With your input:

{"beer":[["lorry1","box2"],["lorry2","box2"]]}{"potatoes":[["lorry1","box2"]]}{"shoes":[["lorry1","box1"],["lorry2","box1"]]}{"snacks":[["lorry1","box1"],["lorry2","box1"]]}

If you want the output as a single JSON object, then collect the above into an array and use add.