Manu Blackwell
Manu Blackwell

Reputation: 43

Problem with json_decode - Syntax error, malformed JSON

I'm receiving a json array from php as the return of curl_exec in PHP (first json PHP -> python, that returns another json), and decode fails due to bad syntax.

The piece of API code:

if($_GET['url'] == 'tomorrowdate'){
    $tomorrow = date('Y-m-d', strtotime(' + 1 days'));
    $risposta = [
        "tomorrow" => $tomorrow
    ];
    echo json_encode($risposta);
    http_response_code(200);
}

the curl code:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, array('Content-type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($ch);
//var_dump($output);
$data = stripslashes($data);
$json_array = json_decode($output, true);

//var_dump(curl_error($ch));

curl_close($ch);

var_dump($json_array);

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;
    }

I tried to adapt your code with mine but the problem remains ...

function remove_utf8_bom($text){
    $bom = pack('H*','EFBBBF');
    $text = preg_replace("/^$bom/", '', $text);
    return $text;
}
$tomorrow = date('Y-m-d', strtotime(' + 1 days'));
$risposta = [
            "tomorrow" => $tomorrow
           ];
$json = remove_utf8_bom($risposta);
echo json_encode($json);
var_dump(json_decode($json_encode, TRUE));

The output is:

{"tomorrow":"2018-09-15"}NULL - Syntax error, malformed JSON

Upvotes: 3

Views: 16439

Answers (2)

Jay Blanchard
Jay Blanchard

Reputation: 34416

Using the following code I can see there is a non-printable character at the beginning of the JSON:

$json = '{"tomorrow":"2018-09-15"}';
var_dump(json_encode($json));

Returns:

string(37) ""\ufeff{\"tomorrow\":\"2018-09-15\"}""

The string ufeff is a BOM. To remove it use the following function:

function remove_utf8_bom($text){
    $bom = pack('H*','EFBBBF');
    $text = preg_replace("/^$bom/", '', $text);
    return $text;
}

which returns:

string(31) ""{\"tomorrow\":\"2018-09-15\"}""

Now using all of the code:

function remove_utf8_bom($text)
{
    $bom = pack('H*','EFBBBF');
    $text = preg_replace("/^$bom/", '', $text);
    return $text;
}
$json = remove_utf8_bom('{"tomorrow":"2018-09-15"}');
var_dump(json_encode($json));
print_r(json_decode($json, TRUE));

Which returns:

string(31) ""{\"tomorrow\":\"2018-09-15\"}""
Array
(
    [tomorrow] => 2018-09-15
)

##EDIT based on comments:

Change the last the lines of your code:

$json = remove_utf8_bom(json_encode($risposta)); // encode here
//echo json_encode($json); // don't really need this, just a test
var_dump(json_decode($json, TRUE)); // you had $json_encode here

This returns EXAMPLE:

array(1) {
  ["tomorrow"]=>
  string(10) "2018-09-15"
}

Upvotes: 15

Rahul Shinde
Rahul Shinde

Reputation: 883

In my case I was getting this error because of PHP version if your php version is less than or equal to 5.4.0 then you have to send all json key values in quotes

I was sending payload like

$payload = array(
    "id" => 36
);

which was failing while decoding json in JWTs decode function I changed to this

$payload = array(
    "id" => "36"
);

and it worked!!!

it is because of json_decode in previous PHP version requires values to be given in quotes. This is block of code from JWT.php JWT library

public static function jsonDecode($input)
{
    if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
        /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
         * to specify that large ints (like Steam Transaction IDs) should be treated as
         * strings, rather than the PHP default behaviour of converting them to floats.
         */
        $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
    } else {
        /** Not all servers will support that, however, so for older versions we must
         * manually detect large ints in the JSON string and quote them (thus converting
         *them to strings) before decoding, hence the preg_replace() call.
         */
        $max_int_length = strlen((string) PHP_INT_MAX) - 1;
        $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
        $obj = json_decode($json_without_bigints);
    }

    if (function_exists('json_last_error') && $errno = json_last_error()) {
        static::handleJsonError($errno);
    } elseif ($obj === null && $input !== 'null') {
        throw new DomainException('Null result with non-null input');
    }
    return $obj;
}
enter code here

Upvotes: 1

Related Questions