PHP: json_encode / json_decode error handling.

Unfortunately, the error handling in the earlier versions of PHP is non-existent. It wasn’t until PHP version 5.3.0 that the function json_last_error was introduced that. Before that, json_encode would return a NULL value or a FALSE value and you’d have to use an external JSON validation tool to try and figure out what was going wrong.

For example, if your data had special (non-UTF8) characters, the json_encode function would often return a NULL value. If the depth of your PHP array was too “deep”, then it would return a FALSE value. The json_decode function was also pretty similar in the way that it returned NULL whenever it received malformed / incorrect JSON strings.

Prior to PHP 5.3.0, JSON error handling in PHP looked a little like this (throwing Exceptions):

or, with json_decode:

Thankfully, in PHP 5.3.0, the function json_last_error was introduced. If an error has occurred, it will return one of the following constants:

  • JSON_ERROR_NONE: No error has occured.
  • JSON_ERROR_DEPTH: Max depth exceeded.
  • JSON_ERROR_STATE_MISMATCH: Invalid JSON.
  • JSON_ERROR_CTRL_CHAR: Bad character was found.

In PHP 5.3.3, another constant was added:

  • JSON_ERROR_UTF8: Bad UTF8 character was found. Incorrect encoding.

Then, in PHP 5.5, they added three more constants:

  • JSON_ERROR_RECURSION: Recursion detected.
  • JSON_ERROR_INF_OR_NAN: One or more NAN or INF values in the value to be encoded.
  • JSON_ERROR_UNSUPPORTED_TYPE: An unsupported type was found.

Using these constants, we can carry out our error handling like so:

Unfortunately, this isn’t the type of code that you should be repeating throughout your script. If you stay true to the DRY (Don’t Repeat Yourself) principle (which you should), then you will wrap this kind of error checking into a function or a class method.

Personally, I would prefer it if json_last_error returned a string-based error message (like the internal XML library does). That way, you wouldn’t need to implement an ugly-looking switch statement.

Still, at least it is far more informative than it used to be!

Comments

comments