Need help to link several objects to one another (main object) with some specificities.
Hello, I need help to make this rendering from a JSON file. I tried several filters, I never managed to make it work the way I wanted. (This is a simplified example of my JSON file)
Input JSON:
[
{
"id": "AAKG",
"data": "some data...",
"main_id": "none"
},
{
"id": "PMBL",
"data": "some data...",
"main_id": "none"
},
{
"id": "ZDFG",
"data": "some data...",
"main_id": "PMBL"
},
{
"id": "XHGF",
"data": "some data...",
"main_id": "PMBL"
},
{
"id": "LOKJ",
"data": "some data...",
"main_id": "none"
},
{
"id": "JQWC",
"data": "some data...",
"main_id": "none"
},
{
"id": "QQSZ",
"data": "some data...",
"main_id": "none"
},
{
"id": "JQWC",
"data": "some data...",
"main_id": "QQSZ"
},
{
"id": "LLRE",
"data": "some data...",
"main_id": "none"
}
]
Output (what i want):
[
{
"id": "AAKG",
"data": "some data...",
"main_id": "none"
},
{
"id": "PMBL",
"data": "some data...",
"main_id": "none"
"details": [
{
"id": "ZDFG",
"data": "some data...",
"main_id": "PMBL"
},
{
"id": "XHGF",
"data": "some data...",
"main_id": "PMBL"
}
]
},
{
"id": "LOKJ",
"data": "some data...",
"main_id": "none"
},
{
"id": "JQWC",
"data": "some data...",
"main_id": "none"
},
{
"id": "QQSZ",
"data": "some data...",
"main_id": "none"
"details": [
{
"id": "JQWC",
"data": "some data...",
"main_id": "QQSZ"
}
]
},
{
},
{
"id": "LLRE",
"data": "some data...",
"main_id": "none"
}
]
Explanations:
In my input I have only one array that covers all the objects in my file, I would like to link all the objects in an Array that have in the "main_id" key value a specific value other than "none" (with key "details"), to the object (which I call the parent object) containing that same value in the "id" key of the parent object.
As you can see in my output example, which I think is more explicit than my explanations. Of course my real input file contains many more objects but the structure remains the same as in my example. [object,object,object,....]
CodePudding user response:
A simple reduce
with an if
expression builig up an indexed object may suffice. The final map
converts the object back to an array.
reduce .[] as $i ({};
if $i.main_id == "none" then .[$i.id] = $i
else .[$i.main_id].details = [$i] end
) | map(.)
[
{
"id": "AAKG",
"data": "some data...",
"main_id": "none"
},
{
"id": "PMBL",
"data": "some data...",
"main_id": "none",
"details": [
{
"id": "ZDFG",
"data": "some data...",
"main_id": "PMBL"
},
{
"id": "XHGF",
"data": "some data...",
"main_id": "PMBL"
}
]
},
{
"id": "LOKJ",
"data": "some data...",
"main_id": "none"
},
{
"id": "JQWC",
"data": "some data...",
"main_id": "none"
},
{
"id": "QQSZ",
"data": "some data...",
"main_id": "none",
"details": [
{
"id": "JQWC",
"data": "some data...",
"main_id": "QQSZ"
}
]
},
{
"id": "LLRE",
"data": "some data...",
"main_id": "none"
}
]
CodePudding user response:
The following should work fine if, as in your example, each id
field is unique in the actual input.
group_by(.main_id == "none")
| reduce (.[0] | group_by(.main_id))[] as $d (
.[1] | INDEX(.id);
.[$d[0].main_id] = {details: $d}
) | map(.)