Batailles d'encodage de caractères UTF-8 JSON encode () [dupliquer]
Cette question a déjà une réponse ici:
- UTF-8 tout au long de 13 réponses
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é.
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);
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.
Ma solution est d'insérer cette ligne mysql_query('SET CHARACTER SET utf8');
, avant le SELECT
.
Cette méthode est bonne.
, 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.
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.
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);
}
}
}
}