Reputation: 3435
Given the following JSON:
{
"one": "1",
"two": "2",
"flag": "f1 f2 f3",
"test one": "",
"test two": "",
"test three": ""
}
Is it possible to obtain the following result using jq?
{
"one": "1",
"two": "2",
"flags": ["f1", "f2", "f3"],
"tests": ["one", "two", "three"]
}
Three points are crucial:
Leave unchanged any field that is not flag
or starts with test
Transform flag
(space separated values) into an array
Any field that starts with test
is added to an array (tests
) where the value is the remaining part of the field's name
Upvotes: 0
Views: 607
Reputation: 36646
You can use /=
to update by splitting, startswith
to match at the beginnning of a string, and to_entries
and with_entries
to manipulate entries involving the key name:
jq '
.flag /= " "
| .tests = (to_entries | map(.key | select(startswith("test "))[5:]))
| with_entries(select(.key | startswith("test ") | not))
'
Another, maybe more efficient implementation which loops just once through the object using reduce
could be:
jq '
reduce to_entries[] as {$key, $value} (null;
if $key == "flag" then .flag = $value / " "
elif $key | startswith("test ") then .tests += [$key[5:]]
else .[$key] = $value end
)
'
Given the sample data, both produce:
{
"one": "1",
"two": "2",
"flag": [
"f1",
"f2",
"f3"
],
"tests": [
"one",
"two",
"three"
]
}
Upvotes: 2