I have a json like this
{
"outer1": {
"outer2": {
"outer3": {
"key1": "value1",
"key2": "value2"
}
},
"outer4": {
"key1": "value1",
"key2": "value2"
}
}
}
I want output to be
[outer1.outer2.outer3]
key1 = value1
key2 = value2
[outer1.outer2.outer4]
key1 = value1
key2 = value2
I tried jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json But its not what is what I want exactly
Assuming your input looks like this:
{
"outer1": {
"outer2": {
"outer3": {
"key1": "value1",
"key2": "value2"
},
"outer4": {
"key1": "value1",
"key2": "value2"
}
}
}
}
You could use the --stream option to read the input as a stream of path-value pairs. For instance:
jq --stream -n '
reduce (inputs | select(has(1))) as [$path, $val] ({};
.[$path[:-1] | join(".")][$path[-1]] = $val
)
'
{
"outer1.outer2.outer3": {
"key1": "value1",
"key2": "value2"
},
"outer1.outer2.outer4": {
"key1": "value1",
"key2": "value2"
}
}
Next, format this JSON according to your needs. For example using to_entries for both levels:
jq --stream -nr '
reduce (inputs | select(has(1))) as [$path, $val] ({};
.[$path[:-1] | join(".")][$path[-1]] = $val
)
| to_entries[] | "[\(.key)]", (
.value | to_entries[] | "\(.key) = \(.value)"
), ""
'
[outer1.outer2.outer3]
key1 = value1
key2 = value2
[outer1.outer2.outer4]
key1 = value1
key2 = value2
Alternatively, combine both steps into a single foreach iteration with a sliding context window as state:
jq --stream -nr '
foreach (inputs | select(has(1))) as [$path, $val] ([];
[last, ($path[:-1] | join("."))];
(select(first != last) | "\n[\(last)]"), "\($path[-1]) = \($val)"
)
'
My take is this:
. as $data
| [ path(.. | scalars) ]
| map( . as $p | { prefix: $p[0:-1]|join("."), key: $p[-1], value: $data | getpath($p) })
| group_by(.prefix)[]
| "[\(first.prefix)]", (.[] | "\(.key)=\(.value)")
Basically:
["outer1","outer2","outer3","key1"])outer1.outer2.outer3), a key (key1) and the actual value (value1)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With