Batallas de encoding de caracteres UTF-8 json_encode ()

Búsqueda

Estoy buscando buscar filas que tengan caracteres acentuados. La encoding para la columna ( NAME ) es latin1_swedish_ci .

El código

La siguiente consulta devuelve Abord â Plouffe usando phpMyAdmin:

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

A continuación se muestran los valores esperados (la función se llama db_fetch_all( $result ) ):

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

Los valores mostrados: 5482 5482 Abord â Plouffe Abord â Plouffe

La matriz se codifica usando json_encode :

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

Problema

El navegador web recibe el siguiente valor:

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

En lugar de:

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

(O el equivalente codificado)

Pregunta

La documentación indica que json_encode() funciona en UTF-8. Puedo ver los valores codificados de LATIN1 a UTF-8. Después de la llamada a json_encode() , sin embargo, el valor se vuelve null .

¿Cómo hago json_encode() codificar los valores UTF-8 correctamente?

Una posible solución es usar Zend Framework , pero preferiría no hacerlo si se puede evitar.

 // 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 ); 

En realidad, no está escribiendo su valor codificado de nuevo en la matriz $row , solo está cambiando la variable local $value . Si desea volver a escribir cuando cambie la variable, deberá tratarla como una referencia:

 foreach( $row as &$value ) { 

Personalmente, trataría de evitar referencias cuando sea posible, y en este caso, en su lugar, use array_map según lo publicado por Kemo.

O mysql_set_charset a UTF-8 para obtener los valores de retorno en UTF-8, independientemente de las intercalaciones reales de tablas, como primer paso para migrar la aplicación a UTF-8.

Mi solución es insertar esta línea mysql_query('SET CHARACTER SET utf8'); antes del SELECT Este método es bueno.

Parece que en lugar de ponerlo en una consulta, uno debería poner:

 mysql_set_charset('utf8'); 

después de la statement de mysql connect.

En tu conexión: mysql_set_charset('utf8', $link);

Ejemplo:

  

Espero que ayude un poco.

Pruebe iconv_r($row,"LATIN1","UTF-8//TRANSLIT"); (función a continuación) antes de json_encode() su resultado.

Tengo UTF-8 como la encoding de la tabla y como resultado la encoding del conjunto, pero a veces las personas todavía logran enviar caracteres que no sean UTF-8 a través de formularios y es problemático rastrear cada fuente de entrada, así que también he envuelto json_encode() para hacerlo más seguro. En particular, he tenido cadenas NULL en mí que contienen el símbolo de grado y “comillas inteligentes” que la gente en el Reino Unido parece tan aficionado.

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