javascript $.getjson - jQuery.parseJSON lanza el error "Invalid JSON" debido a comillas simples escapadas en JSON




4 Answers

De acuerdo con el diagrama de la máquina de estados en el sitio web de JSON , solo se permiten caracteres de comillas dobles escapadas, no comillas simples. Los caracteres de comillas simples no necesitan escaparse:


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 de JSON en el Apéndice E de JavaScript: The Good Parts , escribe:

Los objetivos de diseño de JSON debían ser mínimos, portátiles, textuales y un subconjunto de JavaScript. Cuanto menos tengamos que estar de acuerdo para interoperar, más fácilmente podremos interoperar.

Por lo tanto, tal vez decidió que solo se pueden definir cadenas con comillas dobles, ya que esta es una regla menos en la que todas las implementaciones JSON deben estar de acuerdo. Como resultado, es imposible que un solo carácter de comillas dentro de una cadena termine accidentalmente la cadena, porque por definición una cadena solo puede terminar con un carácter de comillas dobles. Por lo tanto, no es necesario permitir que se escape un carácter de comillas simples en la especificación formal.

Al profundizar un poco más, la implementación de JSON para Java de Crockford 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 en los textos que aceptarán:

...

  • Las cadenas se pueden citar con '(comilla simple).

Esto es confirmado por el código fuente de JSONTokener . El método nextString acepta caracteres de comillas simples escapados y los trata como caracteres de 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 en comillas simples, pero se permite que una implementación las acepte.

Así que algunas implementaciones aceptarán comillas simples, pero no debe confiar en esto. Muchas implementaciones populares son bastante restrictivas a este respecto y rechazarán JSON que contiene cadenas con comillas simples y / o comillas simples escapadas.

Finalmente, para vincular esto de nuevo a la pregunta original, jQuery.parseJSON primero intenta usar el analizador JSON nativo del navegador o una biblioteca cargada como json2.js donde corresponda (que en una nota es la biblioteca en la que se basa la lógica jQuery si JSON no está definido). Por lo tanto, jQuery solo 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 );
},

Por lo que sé, estas implementaciones solo se adhieren a la especificación JSON oficial y no aceptan comillas simples, por lo tanto, tampoco jQuery.

ejemplos parameters

Estoy haciendo solicitudes a mi servidor usando jQuery.post() y mi servidor está devolviendo 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 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 manera de pasar correctamente una sola cita a través de JSON?




Entiendo dónde está el problema y cuando veo las especificaciones, queda claro que las comillas simples que no se escapan deben analizarse correctamente.

Estoy utilizando la función jQuery.parseJSON de jquery para analizar la cadena JSON, pero aún obtengo 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 parece a esto (PHP - 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 que almacene la cadena codificada 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 me funcionó fue usar la máscara de bits JSON_HEX_APOS para convertir las comillas simples de esta manera:

json_encode($tmp, JSON_HEX_APOS);

¿Hay otra forma de abordar este problema? ¿Mi código es incorrecto o está mal escrito?

Gracias




Se encontró un problema similar con CakePHP para generar un bloque de script de JavaScript usando el json_encode nativo de json_encode . $contractorCompanies contiene valores que tienen comillas simples y como se explicó anteriormente y el json_encode($contractorCompanies) esperado json_encode($contractorCompanies) no se les escapa porque su JSON es válido.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>

Agregando addlashes () alrededor de la cadena codificada JSON, se escapan las comillas permitiendo que Cake / PHP haga eco del javascript correcto en el navegador. Los errores de JS desaparecen.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>



Estaba intentando guardar un objeto JSON de una solicitud XHR en un atributo de datos * HTML5. Probé muchas de las soluciones anteriores sin éxito.

Lo que finalmente termino haciendo fue reemplazar la comilla simple ' con el código &#39; usando una expresión regular después del método stringify () llame de la siguiente manera:

var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "&#39;");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.



Related

javascript jquery json