Check if string is a valid JSON with jq
The commands and explanations below attempt to use jq
in the least expensive way, just as means to validate JSON. In my opinion, there are tools better suited for this (Like JSONLint), but if the only thing you have at hand is jq
then this is my contribution.
To validate a JSON file and still get the errors in STDERR
output using jq
you can use the following bash one-liner
jq -reM '""' <<<'<MAYBE_INVALID_JSON>' 1>/dev/null
Which reads as:
Execute
jq
with flags:-r
to output a raw value (No processing or formatting)-e
to exit with a code greater than0
if there was an error-M
do not colorize JSON
The first
jq
argument is'""'
which outputs an empty string, effectively preventingjq
from making any processing of the JSON for printing<<<
followed by a string is called a "Here String", and is basically telling bash to treat the string as if it was a file and pass it toSTDIN
(As input to the command).Note that you can replace
<<<'<MAYBE_INVALID_JSON>'
with the path of a file you want to validate and it would still workThen redirect any
STDOUT
output (Which normally will contain the JSON) to/dev/null
, effectively discarding it
You can also get fancier and output a custom message below the errors by using the following:
jq -reM '""' <<<'<MAYBE_INVALID_JSON>' 1>/dev/null || ( exit_code="$?"; echo 'ERROR: Invalid JSON file. See errors above' 1>&2; exit "$exit_code" )
Where the added portion reads as follows:
||
means: If the previous command failed with a non-zero exit code then run the following command- Open a sub-shell with
(
. This is actually needed since we want to exit with the original command's exit code- Set the
exit_code
environment variable to the exit code of the last command$?
- Print custom error message using
echo
exit
the sub-shell with the exit code from the original command$exit_code
- Set the
- Close the sub-shell
From the manual:
-e / --exit-status:
Sets the exit status of jq to 0 if the last output values was neither false nor null, 1 if the last output value was either false or null, or 4 if no valid result was ever produced. Normally jq exits with 2 if there was any usage problem or system error, 3 if there was a jq program compile error, or 0 if the jq program ran.
So you can use:
if jq -e . >/dev/null 2>&1 <<<"$json_string"; then
echo "Parsed JSON successfully and got something other than false/null"
else
echo "Failed to parse JSON, or got false/null"
fi
In fact, if you don't care about distinguishing between the different types of error, then you can just lose the -e
switch. In this case, anything considered to be valid JSON (including false/null) will be parsed successfully by the filter .
and the program will terminate successfully, so the if
branch will be followed.
This is working for me
echo $json_string | jq -e . >/dev/null 2>&1 | echo ${PIPESTATUS[1]}
that returns return code:
- 0 - Success
- 1 - Failed
- 4 - Invalid
Then you can evaluate the return code by further code.