131 votes

Pourquoi json_encode renverrait une chaîne vide

J'ai une structure PHP simple avec 3 tableaux imbriqués.

Je n'utilise pas d'objets particuliers et je construis moi-même les tableaux avec 2 boucles imbriquées.

Voici un exemple du var_dump du tableau que je veux convertir en 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

Dans un autre script, j'ai une structure similaire et json_encode fonctionne bien. Je ne comprends donc pas pourquoi json_encode ne fonctionne pas ici.

Modification : il semble y avoir un problème avec l'encodage. Lorsque mb_detect_encoding retourne ASCII, le json_encode fonctionne, mais lorsque cela retourne UTF8, cela ne fonctionne plus.

Modification 2 : json_last_error() retourne JSON_ERROR_UTF8 ce qui signifie : Caractères UTF-8 mal formés, peut-être encodés incorrectement.

297voto

Matthieu Riegler Points 1546

Après 2 heures de fouille (cf Edits)

J'ai découvert ce qui suit :

  • Dans mon cas, c'est un problème d'encodage
  • mb_detect_encoding retourne probablement une réponse défectueuse, certaines chaînes ne sont probablement pas en UTF-8
  • l'utilisation de utf8_encode() sur ces chaînes a résolu mon problème, mais voir remarque ci-dessous

Voici une fonction récursive qui peut forcer la conversion en UTF-8 de toutes les chaînes contenues dans un tableau :

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

Utilisez-le simplement de la manière suivante :

echo json_encode(utf8ize($data));

Remarque : utf8_encode() encode les chaînes ISO-8859-1 en UTF-8 comme indiqué dans la documentation, donc si vous n'êtes pas sûr de l'encodage d'entrée, iconv() ou mb_convert_encoding() peuvent être de meilleures options comme indiqué dans les commentaires et d'autres solutions.

40voto

Adam Bubela Points 481

Matthieu Riegler a présenté une solution vraiment excellente, cependant j'ai dû la modifier légèrement pour gérer également les objets :

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

Une autre remarque : json_last_error() peut être utile pour le débogage des fonctions json_encode()/json_decode().

39voto

fayd Points 391

Pour moi, la réponse à ce problème était de définir charset=utf8 dans ma connexion PDO.

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

10voto

Alex Points 477

Adam Bubela a également présenté une solution vraiment excellente qui m'a aidé à résoudre mon problème, et voici la fonction simplifiée :

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

    return $d;
}

7voto

Vsevolod Azovsky Points 105

J'ai exactement le même problème sur PHP 5.6. J'utilise Open Server + Nginx sur Windows 7. Tous les jeux de caractères sont définis sur UTF-8. En théorie, selon la documentation officielle, le drapeau

JSON_UNESCAPED_UNICODE

devrait résoudre cela. Malheureusement, ce n'est pas mon cas. Je ne sais pas pourquoi. Toutes les astuces ci-dessus ne résolvent pas mon problème, donc j'ai trouvé ma propre implémentation. Je pense que cela pourrait aider quelqu'un. Au moins, les lettres russes passent le 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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X