2008-10-30 16 views
87

estoy teniendo dificultades para analizar algunos datos JSON devueltos desde mi servidor utilizando jQuery.ajax()jQuery no analizar mi JSON de consulta AJAX

Para realizar el AJAX que estoy usando:

$.ajax({ 
    url: myUrl, 
    cache: false, 
    dataType: "json", 
    success: function(data){ 
    ... 
    }, 
    error: function(e, xhr){ 
    ... 
    } 
}); 

y si vuelvo una gran variedad de artículos a continuación, que trabaja muy bien:

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ] 

la función se denomina éxito y recibe el objeto correcto.

Sin embargo, cuando estoy tratando de volver a un único objeto:

{ title: "One", key: "1" } 

La función de error se llama y contiene xhr 'parsererror'. Intenté incluir el JSON entre paréntesis en el servidor antes de enviarlo por el cable, pero no importa. Sin embargo, si pego el contenido en una cadena en Javascript y luego uso la función eval(), la evalúa perfectamente.

¿Alguna idea de lo que estoy haciendo mal?

Anthony

+0

Relacionado: http://stackoverflow.com/questions/631418/jquery-getjson-ajax-parseerror –

Respuesta

70

Está su envío de datos, Content-Type "*/json" servidor? De lo contrario, modifique los encabezados de respuesta en consecuencia. Enviar "application/json" estaría bien, por ejemplo.

+0

En segundo lugar esta conjetura, tuve el mismo problema una vez y aprendí que sorprendentemente estaba usando el tipo de mime equivocado. Si está probando localhost en Windows, tenga muy en cuenta esto. Intente subirlo a alguna parte y probarlo nuevamente. Si desea que funcione en localhost, realmente tiene que fudgear la solicitud. – Josh

30

Este problema suele deberse a que su solicitud recibió el tipo de mime equivocado. Al desarrollar en su propia computadora, a veces no está recibiendo el tipo de mime apropiado del "servidor", que es su propia computadora. Me encontré con este problema una vez cuando desarrollé abriendo el archivo almacenado localmente en el navegador (por ejemplo, la URL era "c: /project/test.html").

Intente utilizar la propiedad beforeSend para agregar una función de devolución de llamada que anule el tipo de mimo. Esto engañará al código para que se ocupe de json a pesar de que el servidor envía el tipo de mime equivocado y el código de llamada lo recibe. Algunos ejemplos de código están debajo.

El tipo de mime correcto es application/json según this question, pero sé que la aplicación/j-son funcionó cuando lo probé (hace varios años). Probablemente deberías probar application/json primero.

var jsonMimeType = "application/json;charset=UTF-8"; 
$.ajax({ 
type: "GET", 
url: myURL, 
beforeSend: function(x) { 
    if(x && x.overrideMimeType) { 
    x.overrideMimeType(jsonMimeType); 
    } 
}, 
dataType: "json", 
success: function(data){ 
    // do stuff... 
} 
}); 
+0

¡Solo quiero decir que la sugerencia de beforeSend que sugieres funcionó para mí! mi llamada ajax funcionó muy bien en Safari y Chrome, pero no en Firefox. tan pronto como agregué el beforeSend, Firefox se desconectó. ¡¡Guau!! ¡¡Gracias!! –

1

si devuelve un array obras y devolver un solo objeto no, también se podría tratar de devolver el único objeto como una matriz que contiene ese único objeto:

[ { title: "One", key: "1" } ] 

de esa manera va a devolver una estructura de datos coherente, una matriz de objetos, sin importar la carga de datos.

veo que usted ha intentado envolver el único objeto de "paréntesis", y sugerir este con el ejemplo porque por supuesto JavaScript trata [..] de manera diferente que (..)

4
{ title: "One", key: "1" } 

no lo que se Crees.Como una expresión, es un objeto literal, sino como una declaración, es:

{    // new block 
    title:  // define a label called 'title' for goto statements 
     "One", // statement: the start of an expression which will be ignored 
     key:  // ...er, what? you can't have a goto label in the middle of an expression 
       // ERROR 

Desafortunadamente eval() no le da una forma de especificar si usted le está dando una declaración o una expresión, y tiende a adivina mal.

La solución habitual es envolver cualquier cosa entre paréntesis antes de enviarla a la función eval(). Dice que lo ha intentado en el servidor ... claramente, de alguna manera, eso no está llegando. Debe ser resistente al agua que decir en el cliente final, lo que está recibiendo la respuesta XMLHttpRequest:

eval('('+responseText+')'); 

en lugar de:

eval(responseText); 

, siempre y cuando la respuesta no es realmente una expresión un comunicado. (por ejemplo, no tiene varias cláusulas separadas por punto y coma o un salto de línea.)

+0

Creo que jQuery agrega los paréntesis automáticamente al procesar los datos de solicitud. – strager

+2

Esta respuesta fue muy útil para mí, ya que nunca entendí por qué las personas envuelven a JSON entre paréntesis. –

51

De acuerdo con la especificación json.org, su devolución no es válida. Los nombres siempre se citan, por lo que deben ser regresando

{ "title": "One", "key": "1" } 

y

[ { "title": "One", "key": "1" }, { "title": "Two", "key": "2" } ] 

Esto puede no ser el problema con su configuración, ya que se dice uno de ellos trabaja ahora, pero deben fijarse para ser correctos en caso de que necesite cambiar a otro analizador JSON en el futuro.

+2

De hecho, en jQuery 1.4 (por ejemplo) '{key: 'val'}' no es JSON válido. – rfunduk

1

Si se llama al controlador de errores de jQuery y el objeto XHR contiene "error del analizador", es probable que se trate de un error del analizador que vuelve del servidor.

¿Es su escenario de resultados múltiples cuando llama al servicio sin un parámetro, pero se está interrumpiendo cuando intenta proporcionar un parámetro para recuperar el registro individual?

¿De qué backend estás devolviendo esto?

En los servicios ASMX, por ejemplo, ese suele ser el caso cuando los parámetros se suministran a jQuery como un objeto JSON en lugar de una cadena JSON. Si le proporciona a jQuery un objeto JSON real para su parámetro "datos", serializará eso en los pares k, v delimitados estándar & en lugar de enviarlo como JSON.

1

que se encuentran en algunos de mis implementaciones he tenido que añadir:

obj = new Object; obj = (data.obj); 

que parecía resolver el problema. Evaluar o no, pareció hacer exactamente lo mismo para mí.

+0

Utilice el objeto literal al inicializar un nuevo objeto, no el constructor de objetos: var obj = {}; –

+0

Sí, veo, var myArray = [] para matrices y var myObject = {}, gracias por la sugerencia Dreas – Jay

2

Si usted está consumiendo ASP.NET Web Services utilizando jQuery, asegúrese de tener lo siguiente incluido en su web.config:

<webServices> 
    <protocols> 
     <add name="HttpGet"/> 
     <add name="HttpPost"/> 
    </protocols> 
</webServices> 
+1

Crucial para que los servicios web jQuery y .NET funcionen. – Frenchie

2

que tenía un problema similar a este, donde Firefox 3.5 funcionaba bien y analizada mis datos JSON pero Firefox 3.0.6 devolvió un error parse. Resultó que era un espacio en blanco al inicio del JSON que causó que Firefox 3.0.6 arrojara un error. La eliminación del espacio en blanco lo corrigió

33

Las cadenas JSON están envueltas en dobles comillas; las comillas simples no son un sustituto válido.

{"who": "Hello World"} 

es válida, pero esto no es ...

{'who': 'Hello World'} 

Aunque no es tema de la OP, pensamos que vale la pena destacar para otros que aterrizan aquí.

7

tuve este problema y por un poco utilicé

eval('('+data+')') 

para obtener los datos devueltos en un objeto. pero luego más tarde tuvo otros problemas para conseguir una 'falta) en paréntesis' error y descubrió que jQuery tiene una función específica para la evaluación de una cadena para una estructura JSON:

$.parseJSON(data) 

debe hacer el truco. Esto es además de tener su cadena json en el formato apropiado, por supuesto ...

1

jQuery se atasca en ciertas teclas JSON. Estaba enviando este fragmento de JSON en PHP:

echo json_encode((object) array('result' => 'success')); 

Cambiar el nombre de la tecla 'resultado' a otra cosa funciona. Supongo que se trata de una colisión de palabras reservadas de algún tipo, y podría ser un error en jQuery (1.4.2).

1

En un entorno de ColdFusion, una cosa que provocará un error, incluso con JSON bien formada, está teniendo activar la Solicitud de depuración de salida activada en el administrador de ColdFusion (bajo Depuración & registro> Configuración de depuración de salida). La información de depuración se devolverá con los datos JSON y, por lo tanto, la invalidará.

0

Estaba luchando con esto, y dediqué algunas horas a tratar de resolver esto, hasta que usé Firebug para mostrar el objeto de datos.

var data = eval("(" + data.responseText + ")"); 
console.log(data.count); 
1

también probar esto

$.ajax({ 
    url: url, 
    data:datas, 
    success:function(datas, textStatus, jqXHR){ 
    var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('{'))); 
})}; 

en mi caso el servidor responde con carácter desconocido antes de '{'

6

Si están haciendo eco de la respuesta JSON y sus cabeceras no coinciden */json entonces puede usar la API integrada jQuery.parseJSON para analizar la respuesta.

response = '{"name":"John"}'; 
var obj = jQuery.parseJSON(response); 
alert(obj.name === "John"); 
1

que estaba recibiendo estado = ParseError y xhr.status = 200.

El problema para mí era la URL del interior de la respuesta JSON tenían '\' de cambiar a '/' fijo esto.

-1

uso

$data = yourarray(); 
json_encode($data) 

en el lado del servidor. En el lado del cliente use ajax con Datatype JSON y asegúrese de que la codificación de su documento no sea UTF-8 con BOM debe ser UTF-8.

2

Las técnicas " eval() "y" JSON.parse() "usan formatos mutuamente excluyentes.

  • Con "eval()" paréntesis se requiere .
  • Con el paréntesis "JSON.parse()" son prohibido.

Tenga en cuenta que existen funciones "stringify()" que producen el formato "eval". Para ajax, debe usar solo el formato JSON.

Mientras que "eval" incorpora todo el lenguaje JavaScript, JSON usa solo un pequeño subconjunto del idioma. Entre los constructos en el lenguaje JavaScript que "eval" debe reconocer está el "Block statement" (a.k.a. "compound statement"); que es un par o llaves "{}" con algunas frases adentro. Pero las llaves también se utilizan en la sintaxis de los literales de objetos. La interpretación se diferencia por el contexto en el que aparece el código. Algo podría parecerle un objeto literal, pero "eval" lo verá como una declaración compuesta.

En el lenguaje de JavaScript, los literales de objeto se encuentran a la derecha de una tarea.

var myObj = { ...some..code..here... }; 

Los literales de objetos no aparecen por sí solos.

{ ...some..code..here... } // this looks like a compound statement 

Volviendo a la pregunta original del OP, se le preguntó en 2008, él les preguntó por qué la siguiente falla en "eval()":

{ title: "One", key: "1" } 

La respuesta es que se ve como una sentencia compuesta. Para convertirlo en un objeto, debe ponerlo en un contexto donde una declaración compuesta es imposible. Esto se hace poniendo entre paréntesis alrededor

({ title: "One", key: "1" }) // not a compound statment, so must be object literal 

El PO también preguntó por qué una declaración similar hizo éxito eval:

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ] 

Se aplica la misma respuesta - las llaves están en un contexto en el una declaración compuesta es imposible. Este es un contexto de matriz, "[...]", y las matrices pueden contener objetos, pero no pueden contener sentencias.

A diferencia de "eval()", JSON tiene capacidades muy limitadas. La limitación es intencional. El diseñador de JSON pretendía un subconjunto minimalista de JavaScript, utilizando solo la sintaxis que podría aparecer en el lado derecho de una tarea. Así que si usted tiene algún código que analiza correctamente en JSON ...

var myVar = JSON.parse("...some...code...here..."); 

... que implica también analizará legalmente en el lado derecho de una asignación, como este ..

var myVar = ...some..code..here... ; 

Pero esa no es la única restricción en JSON. El BNF language specification for JSON es muy simple. Por ejemplo, no permite el uso de comillas simples para indicar cadenas (como JavaScript y Perl do) y no tiene una forma de expresar un solo carácter como un byte (como 'C'). Desafortunadamente, tampoco permite comentarios (lo que sería realmente bueno al crear archivos de configuración). La ventaja de todas esas limitaciones es que el análisis de JSON es rápido y no ofrece ninguna oportunidad para la inyección de código (una amenaza para la seguridad).

Debido a estas limitaciones, JSON no tiene uso para paréntesis. En consecuencia, un paréntesis en una cadena JSON es un carácter ilegal.

Siempre use formato JSON con el Ajax, por las siguientes razones:

  • Una tubería típica ajax se configurará para JSON.
  • El uso de "eval()" será criticado como un riesgo de seguridad.

Como un ejemplo de una tubería ajax, considere un programa que involucre un servidor Node y un cliente jQuery. El programa cliente utiliza una llamada jQuery que tiene el formato $.ajax({dataType:'json',...etc.});. JQuery crea un objeto jqXHR para su uso posterior, luego empaqueta y envía la solicitud asociada. El servidor acepta la solicitud, la procesa y luego está listo para responder. El programa del servidor llamará al método res.json(data) para empaquetar y enviar la respuesta. De vuelta en el lado del cliente, jQuery acepta la respuesta, consulta el objeto jqXHR asociado y procesa los datos formateados JSON. Todo esto funciona sin necesidad de conversión manual de datos. La respuesta no implica una llamada explícita a JSON.stringify() en el servidor de nodo y ninguna llamada explícita a JSON.parse() en el cliente; eso es todo manejado para ti.

El uso de "eval" está asociado con los riesgos de seguridad de la inyección de código. Puede pensar que no hay forma de que eso suceda, pero los hackers pueden ser bastante creativos. Además, "eval" es problemático para la optimización de Javascript.

Si se encuentra usando una función "stringify()", tenga en cuenta que algunas funciones con ese nombre crearán cadenas que son compatibles con "eval" y no con JSON. Por ejemplo, en el nodo, el siguiente le da función que crea cadenas en formato compatible "eval":

var stringify = require('node-stringify'); // generates eval() format 

Esto puede ser útil, pero a menos que tenga una necesidad específica, probablemente no es lo que quiere.

Cuestiones relacionadas