Detect bad json data in PHP json_decode()?

Here are a couple of things about json_decode :

  • it returns the data, or null when there is an error
  • it can also return null when there is no error : when the JSON string contains null
  • it raises a warning where there is a warning -- warning that you want to make disappear.


To solve the warning problem, a solution would be to use the @ operator (I don't often recommend using it, as it makes debuging a lot more harder... But here, there is not much of a choice) :

$_POST = array(
    'bad data'
);
$data = @json_decode($_POST);

You'd then have to test if $data is null -- and, to avoid the case in which json_decode returns null for null in the JSON string, you could check json_last_error, which (quoting) :

Returns the last error (if any) occurred by last JSON parsing.


Which means you'd have to use some code like the following :

if ($data === null
    && json_last_error() !== JSON_ERROR_NONE) {
    echo "incorrect data";
}

You can also use json_last_error : http://php.net/manual/en/function.json-last-error.php

which as documentation says :

Returns the last error (if any) occurred during the last JSON encoding/decoding.

here is an example

json_decode($string);

switch (json_last_error()) {
    case JSON_ERROR_NONE:
        echo ' - No errors';
    break;
    case JSON_ERROR_DEPTH:
        echo ' - Maximum stack depth exceeded';
    break;
    case JSON_ERROR_STATE_MISMATCH:
        echo ' - Underflow or the modes mismatch';
    break;
    case JSON_ERROR_CTRL_CHAR:
        echo ' - Unexpected control character found';
    break;
    case JSON_ERROR_SYNTAX:
        echo ' - Syntax error, malformed JSON';
    break;
    case JSON_ERROR_UTF8:
        echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
    break;
    default:
        echo ' - Unknown error';
    break;
}

Since PHP 7.3, the json_decode function will accept a new JSON_THROW_ON_ERROR option that will let json_decode throw an exception instead of returning null on error.


Example:

try {  
  json_decode("{", false, 512, JSON_THROW_ON_ERROR);  
}  
catch (\JsonException $exception) {  
  echo $exception->getMessage(); // displays "Syntax error"  
}

I just broke my head over a json syntax error in what appeared to be perfect json: {"test1":"car", "test2":"auto"} from a url encoded string.

But in my case some of the above was html encoded, as adding html_entity_decode($string) did the trick.

$ft = json_decode(html_entity_decode(urldecode(filter_input(INPUT_GET, 'ft', FILTER_SANITIZE_STRING))));

Hopefully this will save someone else some time.