Given the following JSON-object:
{
"meta": {
"data1": {
"keep": { "key": "value" }
}
},
"detail": {
"data2": [
{
"keep1": "keep1value",
"keep2": "keep2value",
"nokeep1": "abc"
}
],
"data3": [
{
"keep1": "keep1value",
"keep2": "keep2value",
"nokeep2": { "abc": "def" }
}
]
},
"drop" : "this"
}
I’m trying to clean it by removing unwanted fields, like "remove", "nokeep1" and "nokeep2".
However objects in the "data2" and "data3" arrays might contain more fields than the example "nokeepX", but will always contain "keep1" and "keep2" which I want to keep.
My desired output is the following JSON:
{
"meta": { "data1": { "keep": { "key": "value" } } },
"detail": {
"data2": [
{
"keep1": "keep1value",
"keep2": "keep2value"
}
],
"data3": [
{
"keep1": "keep1value",
"keep2": "keep2value"
}
]
}
}
I’ve managed to remove the "drop" field with this query:
jq 'def pick($paths): . as $root | reduce ($paths[]|[.]|flatten(1)) as $path ({}; . + setpath($path; $root|getpath($path))); pick([["meta"], ["detail", "data2"], ["detail", "data3"]])'
However I’ve been struggling to figure out how to remove the "nokeepX" fields – is it possible to accomplish this?
2
Answers
Just provide all the concrete paths to
del
:Demo
Or generalize by e.g. traversing all array items (not just the first) using
[]
without indices:Demo
Or go arbitrarily deep using
..
, and just provide the deepest field names:Demo
Output:
For the other way round, you could list all the leaf paths using
paths(scalars)
, filter out those where the deepest level.[-1]
doesnot
match your criteria, and usedelpaths
to remove the remaining leafs:Demo
If you have only a limited set of properties, it could be easier not to remove unwanted fields, but create the output from the required fields only:
Output:
The approach can be combined with dropping certain fields:
producing the same output as above.