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
flagor starts withtestTransform
flag(space separated values) into an arrayAny field that starts with
testis added to an array (tests) where the value is the remaining part of the field's name
CodePudding user response:
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"
]
}
