Coder Perfect

Why does json encode yield a null value?

Problem

I’ve got a basic php structure with three nested arrays.

I don’t utilize any specific objects, and I create the arrays myself using two nested loops.

Here’s an example of the array’s var dump that I want to convert to Json.

array (size=2)
  'tram B' => 
    array (size=2)
      0 => 
        array (size=3)
          'name' => string 'Ile Verte' (length=9)
          'distance' => int 298
          'stationID' => int 762
      1 => 
        array (size=3)
          'name' => string 'La Tronche Hôpital' (length=18)
          'distance' => int 425
          'stationID' => int 771
  16 => 
    array (size=4)
      0 => 
        array (size=3)
          'name' => string 'Bastille' (length=8)
          'distance' => int 531
          'stationID' => int 397
      1 => 
        array (size=3)
          'name' => string 'Xavier Jouvin' (length=13)
          'distance' => int 589
          'stationID' => int 438

I have a similar structure in another script, and json encode works perfectly. So I’m not sure why json encode isn’t working here.

There appears to be an issue with the encoding. The json encode function works when mb detect encoding returns ASCII, but not when it returns UTF8.

Edit2: JSON ERROR UTF8 is returned by json last error(), which means: Malformed UTF-8 characters, potentially encoded wrongly.

Asked by Matthieu Riegler

Solution #1

After two hours of digging (cf Edits)

I discovered the following:

Here’s a recursive function that will cause all the strings in an array to be converted to UTF-8:

function utf8ize($d) {
    if (is_array($d)) {
        foreach ($d as $k => $v) {
            $d[$k] = utf8ize($v);
        }
    } else if (is_string ($d)) {
        return utf8_encode($d);
    }
    return $d;
}

Simply put it like this:

echo json_encode(utf8ize($data));

Note: According to the documentation, utf8 encode() converts ISO-8859-1 strings to UTF-8, so if you’re unsure about the input encoding, iconv() or mb convert encoding() may be better options.

Answered by Matthieu Riegler

Solution #2

Matthieu Riegler gave a great approach, but I had to make a few changes to make it work with objects:

function utf8ize($d) {
    if (is_array($d)) 
        foreach ($d as $k => $v) 
            $d[$k] = utf8ize($v);

     else if(is_object($d))
        foreach ($d as $k => $v) 
            $d->$k = utf8ize($v);

     else 
        return utf8_encode($d);

    return $d;
}

Finally, json last error() can be useful for troubleshooting the json encode() and json encode() routines.

Answered by Adam Bubela

Solution #3

Setting charset=utf8 in my PDO connection solved this problem for me.

$dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

Answered by fayd

Solution #4

Adam Bubela also provided an excellent solution that assisted me in resolving my issue, and here is the simplified function:

function utf8ize($d)
{ 
    if (is_array($d) || is_object($d))
        foreach ($d as &$v) $v = utf8ize($v);
    else
        return utf8_encode($d);

    return $d;
}

Answered by Alex

Solution #5

On PHP 5.6, I’m having the same issue. On Windows 7, I run Open Server with Nginx. UTF-8 is used for all charsets. According to the official paperwork, flags are, in theory,

should be able to resolve this. Regrettably, this is not the case in my instance. I do not know, why. All snippets above do not solve my problem, thus I have found my own implementation. I believe it could help someone. At least, Russian letters pass the test.

function utf8ize($d) {
    if (is_array($d) || is_object($d)) {
        foreach ($d as &$v) $v = utf8ize($v);
    } else {
        $enc   = mb_detect_encoding($d);

        $value = iconv($enc, 'UTF-8', $d);
        return $value;
    }

    return $d;
}

Answered by Vsevolod Azovsky

Post is based on https://stackoverflow.com/questions/19361282/why-would-json-encode-return-an-empty-string