Milkncookiez
Milkncookiez

Reputation: 7407

Check if string is a valid JSON with jq

I need to catch an error when lifting a service. The response can be null, a string error message like

error services-migration/foobar: Not found: services-migration/foobar

or a valid JSON when everything is fine. I was wondering if there is a way with jq to simply check if the provided string is a valid JSON. I could ofc check the string for some keywords like error f.e., but I'm looking for a more robust option, where eg. I get a true/false or 1/0 from jq. I was looking through the docs of jq and also some questions here on SO but everything was about finding and picking out key-values from a JSON, but nothing about simply validating a string.

UPDATE:

I've got this:

 result=$(some command)

from which the result is the string error services-migration/foobar: Not found: services-migration/foobar

And then the if statement:

 if jq -e . >/dev/null 2>&1 <<<"$result"; then
    echo "it catches it"
 else
    echo "it doesn't catch it"
 fi

And it always ends up in the else clause.

Upvotes: 66

Views: 86957

Answers (4)

Pipo
Pipo

Reputation: 5093

For a variable content like for a line, that's been working for me

echo "$my_potential_json"|jq empty > /dev/null 2>&1                                                                                                                                                
if [ $? -eq 0 ]; then
    echo "found valid json:$my_potential_json"
    do_whatever....

Upvotes: 3

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

Upvotes: 10

Reddy SK
Reddy SK

Reputation: 1374

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.

Upvotes: 18

Tom Fenech
Tom Fenech

Reputation: 74705

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.

Upvotes: 78

Related Questions