Here is a sample JSON response from my curl:
{
"success": true,
"message": "jobStatus",
"jobStatus": [
{
"ID": 9,
"status": "Successful"
},
{
"ID": 2,
"status": "Successful"
},
{
"ID": 99,
"status": "Failed"
}
]
}
I want to check the status of ID=2. Here is the command I tried:
cat test.txt|jq --arg v "2" '.jobStatus[]|select(.ID == $v)|.status'
response: there is none
I tried value 2
without quotes and still no result.
By contrast, if I try the command with a literal 2
, it works:
cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status'
response:
"Successful"
I'm stuck. Can anyone help me identify the problem?
jq
is data-type-aware:
.ID
, as defined in the JSON input, is a number,
but any command-line argument passed with --arg
(such as v
here) is invariably a string (whether you quote the value or not),
so, in order to compare them, you must use an explicit type conversion, such as with tonumber/1
:
jq --arg v '2' '.jobStatus[] | select(.ID == ($v | tonumber)) | .status' test.txt
Given that you're only passing a scalar argument here, the following solution, using --argjson
(jq
v1.5+) is a bit of an overkill, but it is an alternative to explicit type conversion in that passing a JSON argument in effect passes typed data:
jq --argjson v '{ "ID": 2 }' '.jobStatus[] | select(.ID == $v.ID) | .status' test.txt
peak's answer demonstrates that even --argjson v 2
works (in which case comparing to $v
works directly), which is certainly the most concise solution, but may require an explanation:
Even though 2
may not look like JSON, it is: it is a valid JSON text containing a single value of type number (see json.org).
2
is an unquoted token that starts with a digit that makes it a number in the context of JSON (the JSON string-value equivalent is "2"
, which from the shell would have to be passed as '"2"'
- note the embedded double quotes).Therefore jq
interprets --argjson -v 2
as a number, and comparison .ID == $v
works as intended (note that the same applies to --argjson -v '2'
/ --argjson -v "2"
, where the shell removes the quotes before jq
sees the value).
By contrast, anything you pass with --arg
is always a string value that is used as-is.
In other words: --argjson
, whose purpose is to accept arbitrary JSON texts as strings (such as '{ "ID": 2 }'
in the example above), can also be used to pass number-string scalars to force their interpretation as numbers.
The same technique also works with Boolean strings true
and false
.
Tip of the hat to peak for his help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With