2010-06-03 23 views
41

Cada vez que uso el carácter literal \ u2028 en mi fuente de JavaScript con el tipo de contenido establecido en "text/html; charset = utf-8" obtengo un error de análisis de JavaScript.Error de análisis de Javascript en el carácter unicode ' u2028'

Ejemplo:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 
    "http://www.w3.org/TR/html4/strict.dtd"> 

<html lang="en"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>json</title> 

    <script type="text/javascript" charset="utf-8"> 
    var string = '
 '; 
    </script> 
</head> 
<body> 

</body> 
</html> 

Si el <meta http-equiv> queda fuera todo funciona como se esperaba. He probado esto en Safari y Firefox, ambos exhiben el mismo problema.

¿Alguna idea sobre por qué sucede esto y cómo corregirlo correctamente (sin eliminar la codificación)?

Editar: Después de investigar un poco más, el problema específico era que el carácter del problema se devolvía usando JSONP. Esto fue luego interpretado por el navegador, que lee u2028 como una nueva línea y arroja un error sobre una línea nueva no válida en una cadena.

+0

¿Dónde se obtiene el error de análisis? –

+0

En línea con 'var string = '';' – klaaspieter

Respuesta

68

Sí, es una característica del lenguaje JavaScript, documentada en el estándar ECMAScript (3.a edición sección 7.3), que los caracteres U + 2028 y U + 2029 cuentan como finales de línea. En consecuencia, un analizador de JavaScript tratará cualquier carácter no codificado U + 2028/9 de la misma manera que una nueva línea. Como no puede poner una línea nueva dentro de una cadena literal, obtiene un error de sintaxis.

Esto es una desdichada supervisión en el diseño de JSON: en realidad no es un subconjunto adecuado de JavaScript. Los caracteres U + 2028/9 sin procesar son válidos en los literales de cadena en JSON, y serán aceptados por JSON.parse, pero no así en el propio JavaScript.

Por lo tanto, solo es seguro generar código JavaScript utilizando un analizador JSON si está seguro de que explícitamente \u -paisajes de esos caracteres. Algunos lo hacen, otros no; muchos \u -cape todos los caracteres que no sean ASCII, lo que evita el problema.

+0

Esto es muy útil. La solución es escapar del JSON, luego analizar el lado del cliente. Por ejemplo, http://stackoverflow.com/questions/9691611/print-valid-non-escaped-json-in-a-view-with-rails para Ruby/Rails le dice que haga '$ .parseJSON (" # {{} j xyz.to_json} ")' en una plantilla del lado del servidor. –

+1

Mejor aún: 'JSON.parse (# {j.to_json.inspect})' lo renderizará como una cadena con '\ uXXXX' para cualquier carácter irregular. – tadman

+1

Puede insertar el JSON en una etiqueta de script con su tipo establecido en "application/json". Esto debería evitar el análisis del texto UTF-8 como JavaScript. Después de cargar la página, el JSON se puede analizar utilizando 'JSON.parse()' pasando el 'innerHTML' de la etiqueta del script como parámetro. – tukkajukka

-4

Bueno, eso tiene sentido, ya que le está diciendo al navegador que tanto el HTML como el script usan UTF-8, pero luego especifica un carácter que no está codificado en UTF-8. Cuando especifica "charset = UTF-8", es respoonsible para asegurarse de que los bytes transmitidos al navegador sean realmente UTF-8. El servidor web y el navegador no lo harán por usted en esta situación.

+0

Entonces, ¿cómo resolverlo? El personaje fue ingresado por un usuario del sitio web. Sus datos se almacenan en JSON. Cada vez que solicito el JSON obtengo un error de análisis, porque el personaje está ahí. No puedo simplemente eliminar el personaje, porque es probable que el cliente lo vuelva a ingresar. – klaaspieter

+0

Según los comentarios de [este] (http://stackoverflow.com/questions/1811505/with-jquery-access-json-from-cross-domain-url-where-json-may-be-poorly-formed# 1811737) answer, este es un carácter UTF-8 válido que debe analizarse correctamente. – klaaspieter

2

¿Podría simplemente usar \u2028, en lugar de caracteres reales ?, porque U + 2028 es unicode line seperator, los navegadores pensarían que el carácter de salto de línea real es \n.

No podemos hacer como

x = " 

" 

derecho? pero lo hacemos x = "\n", por lo que podría ser el mismo concepto.

+0

La implementación JSON de Douglas Crockford escapa de la cadena, pero aún arroja el error de análisis. En Safari se usa la implementación JSON nativa, que también arroja el error de análisis. Estamos cargando jsonp para que el navegador intente analizarlo antes de que cualquier otro javascript tenga la posibilidad de eliminar los caracteres no válidos. Probablemente tendré que resolver este lado del servidor. – klaaspieter

+0

Sí, @klaaspieter, probablemente en el lado del servidor, y si tiene que hacer eso, también escape '\ u2029' también – YOU

+0

Por cierto, lo he probado un poco más, la implementación de Douglas Crockford es * no * arrojando el error de análisis. – klaaspieter

11

Bien, para responder a mi propia pregunta.

Normalmente, un analizador JSON elimina estos caracteres problemáticos, porque estaba recuperando JSONP. No estaba usando un analizador JSON, en cambio el navegador intentó analizar el JSON en cuanto se llamó a la devolución de llamada.

La única manera de solucionarlo era asegurarse de que el servidor nunca devuelva estos caracteres cuando solicita un recurso JSONP.

p.s. Mi pregunta fue sobre u2028, según Douglas Crockford's json2 library todos los siguientes caracteres pueden causar estos problemas:

'\ u0000 \ u00ad \ u0600- \ u0604 \ u070f \ u17b4 \ u17b5 \ u200c- \ u200f \ u2028- \ u202f \ u2060- \ u20ff \ uffff \ ufff0- \ uffff '

+2

¿tiene alguna fuente para esa lista? (el enlace bajo douglas Crockford no conduce a ningún lugar útil) – pvgoddijn

+3

@pvgoddijn https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L195 –

+0

Enlace en JSON-js que no se romperá cuando el el archivo/repo se ha actualizado: https://github.com/douglascrockford/JSON-js/blob/c98948ae1944a28e2e8ebc3717894e580aeaaa05/json2.js#L180-L181 – Pistos