Let's say I have a JSON array like this:
[
{
"name": "alpha",
"value": 1
},
{
"name": "beta",
"value": 2
},
...
]
(It contains about 50-100 items; this is a simplified example.)
I want to produce a JSON object from it like this:
{
"alpha": 1,
"beta" 2,
...
}
I think the jq filter for it looks something like this:
.[] | {
"alpha": select(.name == "alpha") | .value,
"beta": select(.name == "beta") | .value,
...
}
That doesn't actually work when I try it on https://jqplay.org/s/SOKd4oCh2k, but I think it's pretty close.
OK now here's the tricky part: sometimes the object with "name": "alpha"
(or "name": "beta"
, etc.) won't actually exist in the input array! In that case, I want to print "alpha": null
or "alpha": ""
. But I can't figure out how to integrate that into my select()
call.
In practice I need this to scrape job metrics from a batch scheduling system, where I'm changing the metrics over time as I run performance tests, so any given metric that I'm querying might not exist for a particular job run, but I still want to see all the other metrics from that job run.
The jq-esque solution to the problem is illustrated by:
jq 'from_entries | {alpha, beta, gamma}' input.json
This will convert the array to an object, and then select the values corresponding to the specified keys if present, while also ensuring all the specified keys are present.
If you have a JSON array of key namess (say $keylist), you could write:
from_entries as $in
| reduce $keylist[] as $key ({}; .[$key]=$in[$key])
Or if you want to specify your own fallback value, say $default:
from_entries as $in
| reduce $keylist[] as $key ({}; .[$key] = $in[$key] // $default)
or perhaps (depending on your detailed requirements):
from_entries as $in
| reduce $keylist[] as $key ({};
.[$key] = if ($in | has($key)) then $in[$key] else $default end)