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 than 0 if there was an error
    • -M do not colorize JSON
  • The first jq argument is '""' which outputs an empty string, effectively preventing jq 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 to STDIN (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 work

  • Then 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
  • 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.

Tags:

Bash

Json

Jq