Having the following json structure:
{
"outerDescription1": {
"innerDescription1": {
"otherProperties": 1,
"items": [
"arrayItem1",
"arrayItem2"
]
}
},
"outerDescription2": {
"innerDescription2": {
"otherProperties": 2,
"items": [
"arrayItem3",
"arrayItem4"
]
}
}
}
I would like to get the following result:
{
"item": "arrayItem1",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem2",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem3",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
{
"item": "arrayItem4",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
Assumption: there are many outerDescription
and innerDescription
keys and they are not known upfront.
Single level unroll is would be simple, but unrolling double-nested objects with different keys is a challenge to me.
The closest what I was able to get was:
jq "with_entries(.value = {outer: .key} .value)[]"
which resulted in:
{
"outer": "outerDescription1",
"innerDescription1": {
"otherProperties": 1,
"items": [
"arrayItem1",
"arrayItem2"
]
}
}
{
"outer": "outerDescription2",
"innerDescription2": {
"otherProperties": 2,
"items": [
"arrayItem3",
"arrayItem4"
]
}
}
But right now, without knowing the next nested key name exactly, I am not able to unroll for a second time in the same way as outer
would be swallowed.
I am using JQ 1.6
CodePudding user response:
You could use path
to find the according paths, and getpath
to retrieve their values:
path(.[][].items[]) as $p
| {item: getpath($p), outer: $p[0], inner: $p[1]}
(getpath($p[:-2]) | del(.items))
{
"item": "arrayItem1",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem2",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem3",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
{
"item": "arrayItem4",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
CodePudding user response:
If you know the name of your items
property, the following program is quite readable:
to_entries[]
| {outer: .key, nested: (.value | to_entries[])}
| {item:.nested.value.items[]}
{outer, inner: .nested.key}
(.nested.value | del(.items))
Output:
{
"item": "arrayItem1",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem2",
"outer": "outerDescription1",
"inner": "innerDescription1",
"otherProperties": 1
}
{
"item": "arrayItem3",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
{
"item": "arrayItem4",
"outer": "outerDescription2",
"inner": "innerDescription2",
"otherProperties": 2
}
CodePudding user response:
Here's a straightforward solution using to_entries
:
to_entries[]
| .key as $outer
| .value
| to_entries[]
| .key as $inner
| .value
| .otherProperties as $otherProperties
| .items[]
| {item: ., $outer, $inner, $otherProperties}