I'm using jq inside a bash script, to parse a JSON returned by an API REST service
This is my code (getting .count value)
# getAPIId
# Parse the answer of query API to get the API ID (checking version name)
# return (echo to stdout) the APIID
function getAPIId() {
local apiId
local version
local -i count
if [ -z $1 ]
then
echo "Use: getAPIId \$apiQuery" >&2
exit 1
else
# Parse answer to API info
count=$(echo "$1"|jq -r '.count')
if [ "$count" == "0" ]
then
echo $1 >&2
echo "ERROR: Cannot find an API called ${APINAME}" >&2
return 1
else
for ((i=0; i<count; i++))
do
version=$(echo $1|jq -r '.list['$i'].version')
if [ "$APIVERSION" == "$version" ] && [ "$APINAME" == "$name" ]
then
apiId=$(echo $1|jq -r '.list['$i'].id')
echo "$apiId"
return 0
fi
done
fi
fi
return 1
}
This is the JSON file I try to parse
{"count":1,"next":"","previous":"","list":[{"id":"6d2822e5-a90d-4738-b7b7-ef7d7848cb48","name":"SwaggerPetstore",
"description":"`special key`","context":"/v2","version":"1.0.0","provider":"admin","status":"CREATED","thumbnailUri":null}],"pagination":{"total":1,"offset":0,"limit":25}}
As you see, the field description contains back tick value. In this case, jq fails and return empty string (as not found value for count)
How can avoid the problem with backtick?
jq
does not have any problem at all with backticks in literal values. You can see that as follows:
$ jq '.value' <<<'{"otherKey": "`otherValue`", "value": "desired value `with backticks`"}'
"desired value `with backticks`"
With respect to the code given in the question, though, it's vastly overcomplicated. Rather than muddle through what could be wrong, consider the following replacement (which doesn't need to read count
at all, and calls jq
only once):
# Aside: Using all-caps names is bad practice. Don't do this.
APINAME=SwaggerPetstore
APIVERSION=1.0.0
getAPIId() {
[[ $1 ]] || { echo 'Usage: getAPIId "$json"' >&2; return 1; }
jq -er \
--arg target_name "$APINAME" \
--arg target_version "$APIVERSION" '
.list[] |
select(.name == $target_name) |
select(.version == $target_version) |
.id' <<<"$1"
}
...returns, when called as follows:
s='{
"count": 1,
"next": "",
"previous": "",
"list": [
{
"id": "6d2822e5-a90d-4738-b7b7-ef7d7848cb48",
"name": "SwaggerPetstore",
"description": "`special key`",
"context": "/v2",
"version": "1.0.0",
"provider": "admin",
"status": "CREATED",
"thumbnailUri": null
}
],
"pagination": {
"total": 1,
"offset": 0,
"limit": 25
}
}'
getAPIId "$s"; echo "Exit status is $?" >&2
...the correct result of:
6d2822e5-a90d-4738-b7b7-ef7d7848cb48
Exit status is 0
...whereas if we run it again with an invalid name or version to search for:
APINAME=NotFound getAPIId "$s"; echo "Exit status is $?" >&2
...correctly reflects that:
Exit status is 4