jq -n --argjson
A tip for using jq with more than one input
jq
, a tool for manipulating JSON data, is one of the easiest most powerful ways to work with JSON text values in a terminal. I use it frequently. Mostly, I use it to extract values from HTTP responses:
$ http get https://api.github.com/repos/grafana/grafana | jq '{ name: .name, stars: .stargazers_count }'
{
"name": "grafana",
"stars": 65313
}
The other day I wanted to use jq to combine the values from two different API calls, so I pulled up the man page and found the --argjson
option. Easy, I thought: just write a zsh function:
together() {
orgjson=$(http get https://api.github.com/orgs/$1)
repojson=$(http get https://api.github.com/repos/$1/$2)
jq --argjson org $orgjson --argjson repo $repojson '{ org: $org.name, repo: $repo.name }'
}
This blocks forever. It blocks forever because jq
is waiting on data to come in via stdin for it to process, even when it also has arguments to process. You can observe this by writing to the stdin file descriptor you find in /prod/<pid>/fd/
, or closing the descriptor, which will terminate jq
.
To run jq when no input is expected, use --null-input
or -n
. As the manual says:
--null-input / -n:
Don´t read any input at all. Instead, the filter is run once using null as the input. This is
useful when using jq as a simple calculator or to construct JSON data from scratch.
Add that to the function:
together() {
orgjson=$(http get https://api.github.com/orgs/$1)
repojson=$(http get https://api.github.com/repos/$1/$2)
jq -n --argjson org $orgjson --argjson repo $repojson '{ org: $org.name, repo: $repo.name }'
}
And we get:
$ together grafana grafana
{
"org": "Grafana Labs",
"repo": "grafana"
}