2009-02-24 12 views
67

Estoy escribiendo un servicio web que usa json para representar sus recursos, y estoy un poco atascado pensando en la mejor manera de codificar el json. Al leer el json rfc (http://www.ietf.org/rfc/rfc4627.txt) queda claro que la codificación preferida es utf-8. Pero el rfc también describe un mecanismo de escape de cadena para especificar caracteres. Supongo que esto generalmente se usaría para escapar de caracteres no ascii, por lo que el utf-8 resultante es válido como ascii.Codificación de caracteres JSON: ¿el navegador UTF-8 está bien soportado o debería usar secuencias de escape numéricas?

Digamos que tengo una cadena json que contiene caracteres Unicode (puntos de código) que no son ascii. ¿Debería mi servicio web simplemente utf-8 codificar eso y devolverlo, o debería escapar de todos esos caracteres no ascii y devolver ascii puro?

Me gustaría que los navegadores puedan ejecutar los resultados usando jsonp o eval. ¿Eso afecta la decisión? Mi conocimiento del soporte JavaScript de varios navegadores para utf-8 es deficiente.

EDIT: Quería aclarar que mi principal preocupación sobre cómo codificar los resultados es realmente sobre el manejo del navegador de los resultados. Lo que he leído indica que los navegadores pueden ser sensibles a la codificación cuando usan JSONP en particular. No he encontrado ninguna información realmente buena sobre el tema, así que tendré que comenzar a hacer algunas pruebas para ver qué pasa. Idealmente, me gustaría escapar de esos pocos caracteres que son necesarios y solo utf-8 codificar los resultados.

Respuesta

63

Todos los analizadores JSON pueden manejar adecuada UTF-8 tan bien como las secuencias de escape numéricos, como la especificación JSON requiere.

La capacidad de los codificadores JSON para utilizar las secuencias de escape numéricas en su lugar simplemente le ofrece más opciones. Una razón por la que puede elegir las secuencias de escape numéricas sería si un mecanismo de transporte entre su codificador y el decodificador deseado no es binario seguro.

Otra razón es posible que las secuencias de escape numéricos es evitar que ciertos personajes que aparecen en la corriente, como <, & y ", lo que puede interpretarse como secuencias HTML si el código JSON se coloca sin escapar en HTML o un navegador erróneamente lo interpreta como HTML. Esto puede ser una defensa contra la inyección de HTML o scripts entre sitios (nota: algunos caracteres DEBEN escaparse en JSON, incluidos " y \).

Algunos marcos, incluida la implementación de JSON de PHP, siempre hacen las secuencias de escape numérico en el lado del codificador para cualquier carácter fuera de ASCII. Esto está diseñado para una compatibilidad máxima con mecanismos de transporte limitados y similares. Sin embargo, esto no debe interpretarse como una indicación de que los decodificadores JSON tienen un problema con UTF-8.

lo tanto, supongo que sólo podría decidir cuál usar así:

  • sólo tiene que utilizar UTF-8, a menos que su forma de almacenamiento o transporte entre codificador y decodificador no es en modo binario seguro.

  • De lo contrario, utilice las secuencias de escape numéricas.

10

ASCII ya no figura. El uso de la codificación UTF-8 significa que no está utilizando la codificación ASCII. Lo que debe utilizar el mecanismo de escape para es lo que el RFC dice:

caracteres Todo Unicode pueden ser colocados dentro de las comillas, excepto para los personajes que deben estar escaparon: comilla, revertir solidus, y los caracteres de control (U + 0000 a U + 001F)

+0

Si leer esa cita que ya ha proporcionado verá que usted no está obligado a escapar de todos los caracteres Unicode, sólo unos pocos caracteres especiales. Pero se requiere que codifique los resultados (preferiblemente con utf-8). Entonces, la pregunta es: "¿Por qué molestarse en escapar de los caracteres Unicode normales si está usando la codificación UTF-8?". – schickb

+0

Además, una cadena codificada en ascii es un subconjunto puro de utf-8. Si utilizo el escape de json para todos los caracteres no ascii, el resultado es ascii y, por lo tanto, utf-8. Varias bibliotecas json (como python simplejson) tienen modos para forzar resultados ascii. Supongo que por una razón, como quizás la ejecución en los navegadores. – schickb

+0

Cuando se molesta en escapar de los caracteres Unicode normales se encuentra en contextos donde son metacaracteres, como cadenas. (El fragmento de RFC que cité trata sobre cadenas, lo siento, no estaba claro al respecto). No necesita hacer salidas ASCII todo el tiempo; Creo que eso es más para la depuración con navegadores rotos. – chaos

14

Tuve un problema allí. Cuando codigo JSON una cadena con un caracter como "é", cada navegador devolverá el mismo "é", excepto IE que devolverá "\ u00e9".

Luego con PHP json_decode(), fallará si encuentra "é", entonces para Firefox, Opera, Safari y Chrome, tengo que llamar a utf8_encode() antes de json_decode().

Nota: con mis pruebas, IE y Firefox están utilizando su objeto JSON nativo, otros navegadores usan json2.js.

+10

Probablemente querías decir 'utf8_encode()', http://php.net/manual/en/function.utf8-encode.php – Binyamin

+4

Si IE no puede decodificar eso, es un error en cualquier decodificador JSON que estés usando. Todos los decodificadores JSON deben decodificar correctamente la forma codificada, o no son un decodificador JSON. En cuanto a su problema con json_decode() con el é unescaped, es posible que el texto que lo está alimentando no sea UTF-8. Los decodificadores JSON siempre asumen UTF-8, incluso la implementación PHP, aunque PHP normalmente no asume UTF-8 en muchas otras funciones. Existen otras codificaciones de caracteres que pueden incluir un é y una apariencia idéntica en la pantalla, pero que no son UTF-8. La codificación en el formulario \ uXXXX es una solución a esto. – thomasrutter

+0

Solo digo: JSON puede venir legalmente en cualquier codificación Unicode (UTF-8, UTF-16 BE/LE, UTF32 BE/LE, con o sin marcador de orden de bytes). Y dado que ASCII es un subconjunto de UTF-8, también puede venir en ASCII. Si los analizadores aceptan UTF-32 por ejemplo, no lo sé. – gnasher729

0

Tuve un problema similar con é char ... Creo que el comentario "es posible que el texto que estás alimentando no sea UTF-8" probablemente esté cerca de la marca aquí. Tengo la sensación de que la intercalación predeterminada en mi instancia era otra cosa hasta que me di cuenta y cambié a utf8 ... el problema es que los datos ya estaban allí, así que no estoy seguro si convirtió los datos o no cuando lo cambié, se muestra bien en mysql banco de trabajo. El resultado final es que php no codificará json los datos, simplemente devuelve falso. No importa qué navegador use ya que es el servidor el que causa mi problema, php no analizará los datos en utf8 si este mensaje está presente. Como digo, no estoy seguro de si se debe convertir el esquema a utf8 después de que haya datos o solo un error de php. En este caso use json_encode(utf8_encode($string));

3

Estaba enfrentando el mismo problema. Esto funciona para mi. Por favor, chequee esto.

json_encode($array,JSON_UNESCAPED_UNICODE); 
Cuestiones relacionadas