18 votos

Cómo mantener json_encode() que se caigan las cadenas con caracteres no válidos

Es allí una manera de mantener a json_encode() de devolución de null una cadena que contiene no es válida (no UTF-8) carácter?

Puede ser un dolor en el culo para depurar en un sistema complejo. Sería mucho más adecuado, para ver realmente el carácter no válido, o al menos lo han omitido. Tal y como está, json_encode() silenciosamente caída de toda la cadena.

Ejemplo (en UTF-8):

$string = 
  array(utf8_decode("Düsseldorf"), // Deliberately produce broken string
        "Washington",
        "Nairobi"); 

print_r(json_encode($string));

Resultados en

[null,"Washington","Nairobi"]

Resultado deseado:

["D�sseldorf","Washington","Nairobi"]

Nota: yo no buscan hacer roto las cadenas de trabajo en json_encode(). Estoy buscando maneras de hacer que sea más fácil de diagnosticar los errores de codificación. Un null cadena no es útil para eso.

21voto

goat Puntos 17643

php intenta arrojar un error, pero sólo si activa el display_errors off. Esto es extraño, porque el display_errors ajuste sólo está destinado para el control de si o no los errores se imprime en la salida estándar, no se si es o no un error se activa. Quiero enfatizar que, cuando ha display_errors , incluso aunque usted puede ver todo tipo de errores de php, php no sólo ocultar este error, no vaya a disparar. Eso significa que no va a aparecer en ningún registro de error, ni cualquier personalizado error_handlers llamado. El error nunca se produce.

Aquí está el código que se muestra esto:

error_reporting(-1);//report all errors
$invalid_utf8_char = chr(193);

ini_set('display_errors', 1);//display errors to standard output
var_dump(json_encode($invalid_utf8_char));
var_dump(error_get_last());//nothing

ini_set('display_errors', 0);//do not display errors to standard output
var_dump(json_encode($invalid_utf8_char));
var_dump(error_get_last());// json_encode(): Invalid UTF-8 sequence in argument

Que extraño y lamentable comportamiento está relacionado con este error https://bugs.php.net/bug.php?id=47494 y algunos otros, y no parece que nunca va a ser fijo.

solución:

La limpieza de la cadena antes de pasar a json_encode puede ser una solución viable.

$stripped_of_invalid_utf8_chars_string = iconv('UTF-8', 'UTF-8//IGNORE', $orig_string);
if ($stripped_of_invalid_utf8_chars_string !== $orig_string) {
    // one or more chars were invalid, and so they were stripped out.
    // if you need to know where in the string the first stripped character was, 
    // then see http://stackoverflow.com/questions/7475437/find-first-character-that-is-different-between-two-strings
}
$json = json_encode($stripped_of_invalid_utf8_chars_string);

http://php.net/manual/en/function.iconv.php

El manual dice que

//IGNORE descarta silenciosamente personajes que son ilegales en el destino conjunto de caracteres.

Así que por primera extracción de la problemática de los personajes, en teoría json_encode() no debe recibir nada va a ahogar y se producirá. No he verificado que la salida de iconv con la //IGNORE bandera es perfectamente compatible con json_encodes noción de lo que es válido de caracteres utf8, por lo que el comprador tenga cuidado...como puede haber casos extremos en que el error persiste. ugh, odio conjunto de caracteres problemas.

3voto

Danack Puntos 8764

Esta función permite eliminar todos válidos UTF8 caracteres de una cadena:

function removeInvalidChars( $text) {
    $regex = '/( [\x00-\x7F] | [\xC0-\xDF][\x80-\xBF] | [\xE0-\xEF][\x80-\xBF]{2} | [\xF0-\xF7][\x80-\xBF]{3} ) | ./x';
    return preg_replace($regex, '$1', $text);
}

Yo lo uso después de la conversión de un documento de Excel para json, como el Excel de google docs no están garantizados para estar en UTF8.

Yo no creo que haya una particular forma sensata de la conversión de caracteres no válidos para un visible, pero de carácter válido. Usted podría reemplazar caracteres no válidos con U+FFFD que es el unicode carácter de sustitución girando el regex por encima de todo, pero que realmente no proporcionan una mejor experiencia de usuario que acaba de caer caracteres no válidos.

2voto

metamatt Puntos 3276

Usted necesita saber la codificación de todas las cadenas que te estás enfrentando, o estás entrando en un mundo de dolor.

UTF-8 es una fácil codificación a utilizar. También, JSON se define el uso de UTF-8 (http://www.json.org/JSONRequest.html). Así que ¿por qué no usarlo?

Respuesta corta: el camino para evitar json_encode() soltando las cadenas es para asegurarse de que son válidos UTF-8.

2voto

miro Puntos 31
$s = iconv('UTF-8', 'UTF-8//IGNORE', $s);

Ya esta resuelto el problema. No estoy seguro de por qué los chicos de php no han hecho la vida más fácil a través de la fijación json_encode().

De todos modos con la anterior permite json_encode() para crear el objeto, incluso si los datos que contiene caracteres especiales (sueca de las letras, por ejemplo).

Usted puede utilizar el resultado en javascript sin necesidad de decodificación de los datos de nuevo a su codificación original (con escape(), unescape(), encodeURIComponent(), decodeURIComponent());

La estoy usando como este en php (smarty):

$template = iconv('UTF-8', 'UTF-8//IGNORE', $screen->fetch("my_template.tpl"));

A continuación, le estoy enviando el resultado a javascript y sólo innerHTML la plantilla lista html (la paz) en mi documento.

Simplemente dijo por encima de la línea debe ser implementado en json_encode() de alguna manera con el fin de permitir que funcione con cualquier codificación.

-1voto

CR7 Puntos 49

En lugar de utilizar la función iconv, usted puede directamente utilice el json_encode con el JSON_UNESCAPED_UNICODE opción ( >= PHP5.4.0 )

Asegúrese de poner el "charset=utf-8" en el encabezado de su archivo php:

header('Content-Type: application/json; charset=utf-8');

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: