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)"
)
'