jQuery.parseJSON arroja el error "JSON no válido" debido a una comilla simple escapada en JSON

Resuelto Felix asked hace 14 años • 7 respuestas

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?

Felix avatar Feb 17 '10 01:02 Felix
Aceptado

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:

http://www.json.org/string.gif


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 nextStringmé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.parseJSONprimero 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 JSONno 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.

Justin Ethier avatar Feb 16 '2010 18:02 Justin Ethier

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

Erik Čerpnjak avatar Oct 30 '2014 08:10 Erik Čerpnjak

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,"'","''")

BehranG BinA avatar Nov 22 '2012 05:11 BehranG BinA