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
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
.