8

This is probably a really simple question, but I just can't find any info on it.

I work with a system that aggregates a lot of data from various sources and then stores that data in a database. For the most part, the system works fine, but occasionally we get an issue where data can have awkward character encoding (for instance, when the data is in another language, like French) that our system doesn't like.

The data gets passed to our processing server (we use Gearman), and to ensure that all the info pertaining to source gets passed we json_encode an array with everything we need. My question to you is: if I wrap the json_encode in a try/catch block, will things that cause "PHP Warning: json_encode(): Invalid UTF-8 sequence in argument" messages trigger the catch block to activate?

Thanks!

Lisa
  • 2,102
  • 7
  • 26
  • 44
  • I don't think `json` throws Exceptions ... – Mihai Iorga Sep 04 '12 at 14:40
  • You want to ask if it will create warning if you do it or it is creating warning and you have already tried it? – Wearybands Sep 04 '12 at 14:40
  • 1
    You can try to prepend your call with an `@` to suppress errors and check the return value. eg. `if (($str = @json_encode($foo)) !== FALSE) { ...do your stuff, encoding succeeded... }` – ccKep Sep 04 '12 at 14:42

4 Answers4

14

No but you can check it's return value in a function and throw an exception when something goes wrong. You can also use json_last_error to get details on the error

Example:

function my_json_encode($data) {
    if( json_encode($data) === false ) {
        throw new Exception( json_last_error() );
    }
}

try {
    my_json_encode($data);
}
catch(Exception $e ) {
    // do something
}

I do find it highly annoying that to get the actual error message you have to check a list of constants that is returned from json_last_error(). In the past I've used a switch / case statement to make that happen but you could throw different exceptions depending on the error.

Cfreak
  • 19,191
  • 6
  • 49
  • 60
1

Not natively, you will need to set up some custom error handling.

<?php

function exception_error_handler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

set_error_handler('exception_error_handler');

Then you can do:

try
{
    json_encode(...);
}
catch (ErrorException $e)
{
    // do some thing with $e->getMessage()
}

But bare in mind that this will cause all PHP errors to throw an exception, so you should fine tune it to your needs.

Matt Humphrey
  • 1,554
  • 1
  • 12
  • 30
  • A good writeup on this concept can be found here: http://stackoverflow.com/questions/3425835/php-converting-errors-to-exceptions-design-flaw – SDC Sep 04 '12 at 15:31
1

You can also Output errors or show exception on basis of errors. Like see code below.

<?php


protected static $_messages = array(
    JSON_ERROR_NONE => 'No error has occurred',
    JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
    JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
    JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
    JSON_ERROR_SYNTAX => 'Syntax error',
    JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
);

public static function encode($value, $options = 0) {
    $result = json_encode($value, $options);

    if($result)  {
        return $result;
    }

    throw new RuntimeException(static::$_messages[json_last_error()]);
}

public static function decode($json, $assoc = false) {
    $result = json_decode($json, $assoc);

    if($result) {
        return $result;
    }

    throw new RuntimeException(static::$_messages[json_last_error()]);
}
Hasnat Safder
  • 2,455
  • 1
  • 17
  • 15
0

Since PHP 7.3, you can use the JSON_THROW_ON_ERROR option. In PHP 5.5 they changed the return value on error for json_encode from null to false. Here's a solution that covers various versions of PHP.

function callJSONFunc($jsonFuncName, $args) {
    if (defined('JSON_THROW_ON_ERROR')) {
        $args[1] = $args || JSON_THROW_ON_ERROR;
    }
    $ret = call_user_func_array($jsonFuncName, $args);
    if (!defined('JSON_THROW_ON_ERROR')) {
        if ($ret === false || $ret === null) {
            throw new JSONException(json_last_error_msg());
        }
    }
    return $ret;
}

class JSONException extends Exception {}

function decodeJSON() { return callJSONFunc('json_decode', func_get_args()); }
function encodeJSON() { return callJSONFunc('json_encode', func_get_args()); }
Raffi
  • 970
  • 11
  • 13