jQuery.parseJSON arroja el error "JSON no válido" debido a una comilla simple escapada en JSON
Estoy realizando solicitudes a mi servidor usando jQuery.post()
y mi servidor devuelve objetos JSON (como { "var": "value", ... }
). Sin embargo, si alguno de los valores contiene una comilla simple (escapada correctamente como \'
), jQuery no puede analizar una cadena JSON que de otro modo sería válida. Aquí hay un ejemplo de lo que quiero decir ( hecho en la consola de Chrome ):
data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }
$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }
¿Esto es normal? ¿No hay forma de pasar correctamente una comilla simple a través de JSON?
Según el diagrama de máquina de estado en el sitio web JSON , solo se permiten caracteres de escape entre comillas dobles, no comillas simples. No es necesario utilizar caracteres de escape entre comillas simples:
Actualización - Más información para aquellos que estén interesados:
Douglas Crockford no dice específicamente por qué la especificación JSON no permite comillas simples escapadas dentro de las cadenas. Sin embargo, durante su discusión sobre JSON en el Apéndice E de JavaScript: The Good Parts , escribe:
Los objetivos de diseño de JSON eran ser mínimos, portátiles, textuales y un subconjunto de JavaScript. Cuanto menos necesitemos acordar para interoperar, más fácilmente podremos interoperar.
Entonces, tal vez decidió permitir que las cadenas solo se definan usando comillas dobles, ya que esta es una regla menos con la que todas las implementaciones JSON deben estar de acuerdo. Como resultado, es imposible que un carácter de comilla simple dentro de una cadena termine accidentalmente la cadena, porque, por definición, una cadena solo puede terminar con un carácter de comilla doble. Por lo tanto, no es necesario permitir el escape de un carácter de comilla simple en la especificación formal.
Profundizando un poco más, la implementación org.json de Crockford de JSON para Java es más permisible y permite caracteres de comillas simples:
Los textos producidos por los métodos toString se ajustan estrictamente a las reglas de sintaxis JSON. Los constructores son más indulgentes con los textos que aceptarán:
...
- Las cadenas pueden ir entre comillas con ' (comilla simple).
Esto lo confirma el código fuente de JSONTokener . El nextString
método acepta comillas simples escapadas y los trata como si fueran comillas dobles:
public String nextString(char quote) throws JSONException {
char c;
StringBuffer sb = new StringBuffer();
for (;;) {
c = next();
switch (c) {
...
case '\\':
c = this.next();
switch (c) {
...
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
...
En la parte superior del método hay un comentario informativo:
El formato JSON formal no permite cadenas entre comillas simples, pero una implementación puede aceptarlas.
Por lo tanto, algunas implementaciones aceptarán comillas simples, pero no debes confiar en esto. Muchas implementaciones populares son bastante restrictivas a este respecto y rechazarán JSON que contenga cadenas entre comillas simples y/o comillas simples escapadas.
Finalmente, para vincular esto con la pregunta original, jQuery.parseJSON
primero intenta usar el analizador JSON nativo del navegador o una biblioteca cargada como json2.js cuando corresponda (que, en una nota al margen, es la biblioteca en la que se basa la lógica jQuery si JSON
no está definida) . Por lo tanto, jQuery sólo puede ser tan permisivo como la implementación subyacente:
parseJSON: function( data ) {
...
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
...
jQuery.error( "Invalid JSON: " + data );
},
Hasta donde yo sé, estas implementaciones solo se adhieren a la especificación JSON oficial y no aceptan comillas simples, por lo tanto, jQuery tampoco.
Entiendo dónde radica el problema y cuando miro las especificaciones, queda claro que las comillas simples sin escape deben analizarse correctamente.
Estoy usando la función jQuery.parseJSON de jquery para analizar la cadena JSON, pero sigo recibiendo el error de análisis cuando hay una comilla simple en los datos preparados con json_encode.
¿Podría ser un error en mi implementación que se ve así (PHP - lado del servidor):
$data = array();
$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);
$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);
$jsonString = "[" . implode(", ", $data) . "]";
El último paso es almacenar la cadena codificada en JSON en una variable JS:
<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>
Si uso "" en lugar de '', todavía arroja un error.
SOLUCIÓN:
Lo único que funcionó para mí fue usar la máscara de bits JSON_HEX_APOS para convertir las comillas simples de esta manera:
json_encode($tmp, JSON_HEX_APOS);
¿Existe otra forma de abordar este problema? ¿Mi código es incorrecto o está mal escrito?
Gracias
Cuando envía una cotización simple en una consulta
empid = " T'via"
empid =escape(empid)
Cuando obtienes el valor incluyendo una cotización simple
var xxx = request.QueryString("empid")
xxx= unscape(xxx)
Si desea buscar/insertar el valor que incluye una comilla simple en una consulta
xxx=Replace(empid,"'","''")