Batailles d'encodage de caractères UTF-8 JSON encode () [dupliquer]

Cette question a déjà une réponse ici:

Quête

Je cherche à récupérer des lignes qui ont des caractères accentués. Le codage de la colonne (NAME) est latin1_swedish_ci.

Le Code

La requête suivante renvoie Abord â Plouffe en utilisant phpMyAdmin:

SELECT C.NAME FROM CITY C
WHERE C.REGION_ID=10 AND C.NAME_LOWERCASE LIKE '%abor%'
ORDER BY C.NAME LIMIT 30

Ce qui suit affiche les valeurs attendues (la fonction est appelée db_fetch_all( $result )):

  while( $row = mysql_fetch_assoc( $result ) ) {
    foreach( $row as $value ) {
      echo $value . " ";
      $value = utf8_encode( $value );
      echo $value . " ";
    }

    $r[] = $row;
  }

Les valeurs affichées: 5482 5482 Abord â Plouffe Abord â Plouffe

Le tableau est ensuite codé en utilisant json_encode:

$rows = db_fetch_all( $result );
echo json_encode( $rows );

Problème

Le navigateur Web reçoit la valeur suivante:

{"ID":"5482","NAME":null}

Au Lieu de:

{"ID":"5482","NAME":"Abord â Plouffe"}

(Ou l'équivalent codé.)

Question

La documentation indique que json_encode() Fonctionne sur UTF-8. Je peux voir la valeurs codées de LATIN1 à UTF-8. Après l'appel à json_encode(), cependant, la valeur devient null.

Comment faire en sorte que json_encode() code correctement les valeurs UTF-8?

Une solution possible est d'utiliser le Zend Framework , mais je préfère ne pas le faire si cela peut être évité.

27
demandé sur Dave Jarvis 2010-05-07 20:19:11

6 réponses

// Create an empty array for the encoded resultset
$rows = array();

// Loop over the db resultset and put encoded values into $rows
while($row = mysql_fetch_assoc($result)) {
  $rows[] = array_map('utf8_encode', $row);
}

// Output $rows
echo json_encode($rows);
38
répondu Kemo 2014-06-03 13:27:22
foreach( $row as $value ) {
  $value = utf8_encode( $value );

Vous n'écrivez pas réellement votre valeur codée dans le tableau $row, vous ne modifiez que la variable locale $value. Si vous voulez réécrire lorsque vous modifiez la variable, vous devez la traiter comme une référence:

foreach( $row as &$value ) {

Personnellement, j'essaierais d'éviter les références si possible, et pour ce cas, utilisez plutôt {[4] } comme posté par Kemo.

Ou mysql_set_charset à UTF-8 pour obtenir les valeurs de retour en UTF-8 indépendamment des collations de table réelles, comme première étape vers la migration de L'application vers UTF-8.

10
répondu bobince 2010-05-07 16:41:42

Ma solution est d'insérer cette ligne mysql_query('SET CHARACTER SET utf8');, avant le SELECT. Cette méthode est bonne.

5
répondu jailsonjan 2012-10-19 19:34:54

, Il semble que, plutôt que de le mettre dans une requête, on devrait mettre:

mysql_set_charset('utf8');

Après l'instruction mysql connect.

4
répondu Robert Imhoff 2013-03-03 08:25:06

Dans votre connexion: mysql_set_charset('utf8', $link);

Exemple:

<?php
$link = mysql_connect('localhost', 'your_user', 'your_password');
mysql_set_charset('utf8', $link);
$db_selected = mysql_select_db('your_db', $link);
...

J'espère que cela aide un peu.

1
répondu alditis 2013-10-22 20:42:57

Essayez iconv_r($row,"LATIN1","UTF-8//TRANSLIT"); (Fonction ci-dessous) avant de json_encode() Votre résultat.

J'ai UTF-8 comme encodage de table et comme encodage de jeu de résultats, mais parfois les gens parviennent toujours à soumettre des caractères non-UTF-8 via des formulaires et il est gênant de traquer chaque source d'entrée, donc j'ai également enveloppé json_encode() pour le rendre plus sûr. En particulier, je l'ai eu des chaînes nulles sur moi contenant le symbole de degré et les "citations intelligentes" dont les gens au Royaume-Uni semblent si friands.

function safe_json_encode($mixed,$missing="TRANSLIT"){
   $out=json_encode($mixed);
   if ($err=  json_last_error()){
      iconv_r("UTF-8","UTF-8//$missing",$mixed);
      $out=json_encode($mixed);
   }
   return $out;
}
function iconv_r($charset_i, $charset_o, &$mixed) {
   if (is_string($mixed)) {
      $mixed = iconv($charset_i, $charset_o, $mixed);
   } else {
      if (is_object($mixed)){
         $mixed = (array) $mixed;
      }
      if (is_array($mixed)){
         foreach ($mixed as $key => &$value) {
            iconv_r($charset_i, $charset_o, $value);
         }
      }
   }
}
0
répondu Wil 2014-06-05 01:53:57