web-dev-qa-db-fra.com

jQuery n'analysera pas mon JSON à partir de AJAX query

Je ne parviens pas à analyser certaines données JSON renvoyées par mon serveur à l'aide de jQuery.ajax ().

Pour effectuer le AJAX j'utilise:

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

Et si je retourne un tableau d’éléments, cela fonctionnera bien:

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

La fonction de réussite est appelée et reçoit le bon objet.

Cependant, lorsque j'essaie de renvoyer un seul objet:

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

La fonction d'erreur est appelée et xhr contient 'parsererror'. J'ai essayé d'encapsuler le JSON entre parenthèses sur le serveur avant de l'envoyer par le fil, mais cela ne fait aucune différence. Pourtant, si je colle le contenu dans une chaîne en Javascript et que j'utilise ensuite la fonction eval (), il l'évalue parfaitement.

Des idées que je fais mal?

Anthony

87
littlecharva

Votre serveur envoie-t-il des données en tant que Content-Type "*/json"? Sinon, modifiez les en-têtes de réponse en conséquence. Envoi en cours "application/json" serait bien, par exemple.

71
Tomalak

Selon la spécification json.org , votre déclaration est invalide. Les noms sont toujours cités, vous devriez donc y retourner

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

et

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

Ce n’est peut-être pas le problème de votre configuration, puisque vous dites que l’une d’elles fonctionne maintenant, mais il convient de corriger cette erreur si vous devez utiliser un autre analyseur JSON à l’avenir.

51
Ben Combee

Les chaînes JSON sont encapsulées dans des guillemets double; les guillemets simples ne constituent pas un substitut valable.

{"who": "Hello World"}

est valide mais ce n'est pas ...

{'who': 'Hello World'}

Bien que ce ne soit pas le problème du PO, j'ai pensé que cela méritait d'être noté pour les autres qui atterrissent ici.

33
John Mee

Ce problème provient généralement du fait que votre demande a reçu un type de mime incorrect. Lorsque vous développez sur votre propre ordinateur, vous ne recevez parfois pas le type de mime approprié du "serveur", qui est votre propre ordinateur. J'ai rencontré ce problème une fois lors du développement en ouvrant le fichier stocké localement dans le navigateur (par exemple, l'URL était "c: /project/test.html").

Essayez d’utiliser la propriété beforeSend pour ajouter une fonction de rappel qui remplace le type mime. Cela incitera le code à traiter avec json malgré le mauvais type de mime envoyé par le serveur et reçu par votre code d'appel. Un exemple de code est ci-dessous.

Le type de mime approprié est application/json selon cette question , mais je sais que l’application/j-son a fonctionné lorsque j’ai essayé (il ya maintenant plusieurs années). Vous devriez probablement essayer d'abord application/json.

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...
 }
});
30
Josh

J'ai eu ce problème et pour un peu j'ai utilisé

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

pour obtenir les données retournées dans un objet. mais plus tard, d'autres problèmes se sont posés une erreur "manquant) entre parenthèses" et ont découvert que jQuery avait une fonction spécifique pour évaluer une chaîne pour une structure json:

$.parseJSON(data)

devrait faire l'affaire. Ceci est en plus d'avoir votre chaîne json dans le bon format bien sûr ..

7
Jubair

Si vous faites écho à la réponse JSON et que vos en-têtes ne correspondent pas à */json, vous pouvez utiliser l’API intégrée jQuery.parseJSON pour analyser la réponse.

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );
6
Nezzy
{ title: "One", key: "1" }

N'est-ce pas ce que vous pensez? En tant qu'expression, il s'agit d'un littéral Object, mais en tant qu'énoncé, il s'agit de:

{                // 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

Malheureusement, eval () ne vous donne pas le moyen de spécifier si vous lui donnez une déclaration ou une expression, et il a tendance à mal deviner.

La solution habituelle est en effet de mettre n'importe quoi entre parenthèses avant de l’envoyer à la fonction eval (). Vous dites que vous avez essayé cela sur le serveur ... clairement que cela ne passe pas. Il devrait être étanche de dire, côté client, tout ce qui reçoit la réponse XMLHttpRequest:

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

au lieu de:

eval(responseText);

tant que la réponse est vraiment une expression pas une déclaration. (par exemple, il n'a pas plusieurs clauses, séparées par des points-virgules ou des sauts de ligne.)

4
bobince

Vous devrez définir le type de contenu d'en-tête dans votre php comme ceci:

 <?php

 header('Content-type:application/json');

 ?>

Regardez cette vidéo pour une meilleure compréhension ....

Référence: http://www.youtube.com/watch?v=EvFXWqEqh6o

3
user3612872

J'ai eu un problème similaire à celui-ci: Firefox 3.5 fonctionnait correctement et analysait mes données JSON, mais Firefox 3.0.6 renvoyait un analyseur syntaxique. Il s’est avéré que c’est un espace vide au début du JSON qui a provoqué une erreur dans Firefox 3.0.6. Suppression de l'espace vide corrigé

2
jonburney

Les techniques "eval ()" et "JSON.parse ()" utilisent des formats mutuellement exclusifs.

  • Avec "eval ()", les parenthèses sont obligatoires .
  • Avec "JSON.parse ()", les parenthèses sont interdites .

Attention, il existe des fonctions "stringify ()" qui produisent le format "eval". Pour ajax, vous devez utiliser uniquement le format JSON.

Alors que "eval" intègre l’ensemble du langage JavaScript, JSON n’utilise qu’un sous-ensemble du langage. Parmi les constructions dans le langage JavaScript que "eval" doit reconnaître, il y a "Instruction block" (a.k.a. "instruction composée") ; qui est une paire ou des accolades "{}" avec quelques déclarations à l'intérieur. Mais les accolades sont également utilisées dans la syntaxe des littéraux d'objet. L'interprétation est différenciée par le contexte dans lequel le code apparaît. Quelque chose peut ressembler à un objet au sens littéral, mais "eval" le verra comme une instruction composée.

Dans le langage JavaScript, les littéraux d'objet apparaissent à droite d'un devoir.

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

Les littéraux d'objet ne se produisent pas d'eux-mêmes.

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

Revenant à la question initiale du PO, posée en 2008, il a demandé pourquoi les erreurs suivantes échouaient dans "eval ()":

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

La réponse est que cela ressemble à une déclaration composée. Pour le convertir en objet, vous devez le placer dans un contexte où une instruction composée est impossible. Cela se fait en mettant des parenthèses autour

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

Le PO a également demandé pourquoi une déclaration similaire avait réussi à évaluer:

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

La même réponse s'applique - les accolades se trouvent dans un contexte où une déclaration composée est impossible. Ceci est un contexte de tableau, "[...]", Et les tableaux peuvent contenir des objets, mais ils ne peuvent pas contenir d'instructions.

Contrairement à "eval ()", JSON est très limité dans ses capacités. La limitation est intentionnelle. Le concepteur de JSON a conçu un sous-ensemble minimaliste de JavaScript, en utilisant uniquement la syntaxe susceptible d'apparaître à droite d'une affectation. Donc, si vous avez du code qui analyse correctement en JSON ...

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

... cela implique qu'il sera également légalement analysé du côté droit d'une tâche, comme celle-ci.

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

Mais ce n’est pas la seule restriction imposée à JSON. Le spécification de langage BNF pour JSON est très simple. Par exemple, il ne permet pas l'utilisation de guillemets simples pour indiquer des chaînes (comme JavaScript et Perl) et ne permet pas d'exprimer un seul caractère sous forme d'octet (comme le fait "C"). Malheureusement, il ne permet pas non plus de commentaires (ce qui serait vraiment agréable lors de la création de fichiers de configuration). L'avantage de toutes ces limitations est que l'analyse de JSON est rapide et n'offre aucune possibilité d'injection de code (une menace pour la sécurité).

En raison de ces limitations, JSON n'a aucune utilité pour les parenthèses. Par conséquent, une parenthèse dans une chaîne JSON est un caractère illégal.

Utilisez toujours le format JSON avec ajax, pour les raisons suivantes:

  • Un pipeline ajax typique sera configuré pour JSON.
  • L'utilisation de "eval ()" sera critiquée en tant que risque de sécurité.

Comme exemple de pipeline ajax, considérons un programme impliquant un serveur Node) et un client jQuery. Le programme client utilise un appel jQuery ayant la forme $.ajax({dataType:'json',...etc.});. JQuery crée un objet jqXHR pour une utilisation ultérieure, puis empaquette et envoie la demande associée. Le serveur accepte la demande, la traite, puis est prêt à répondre. Le programme serveur appelle la méthode res.json(data) pour empaqueter et envoyer le De retour côté client, jQuery accepte la réponse, consulte l’objet jqXHR associé et traite les données au format JSON. Tout fonctionne sans conversion manuelle des données. La réponse n’implique aucun appel explicite à JSON.stringify () le le serveur Node, et aucun appel explicite à JSON.parse () sur le client; tout cela est géré pour vous.

L'utilisation de "eval" est associée aux risques de sécurité liés à l'injection de code. Vous pensez peut-être qu’il n’ya aucun moyen d’arriver, mais les pirates informatiques peuvent faire preuve de beaucoup de créativité. En outre, "eval" est problématique pour l'optimisation Javascript.

Si vous utilisez une fonction "stringify ()", sachez que certaines fonctions portant ce nom créeront des chaînes compatibles avec "eval" et non avec JSON. Par exemple, dans Node, ce qui suit vous donne une fonction qui crée des chaînes au format compatible "eval":

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

Cela peut être utile, mais à moins que vous n'ayez un besoin spécifique, ce n'est probablement pas ce que vous voulez.

2
IAM_AL_X

Si vous utilisez les services Web ASP.NET avec jQuery, assurez-vous que les éléments suivants sont inclus dans votre fichier Web.config:

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>
2
Andreas Grech

Dans un environnement ColdFusion, une erreur, même avec un JSON bien formé, consiste à avoir Activer la sortie du débogage de la demande activé dans l'administrateur ColdFusion (sous Débogage et journalisation> Paramètres de sortie du débogage). Les informations de débogage seront renvoyées avec les données JSON et les rendront donc invalides.

1
Dave DuPlantis

Je devenais status = parseerror et xhr.status = 200.

Le problème pour moi était que l'URL dans la réponse JSON avait "\" basculé sur "/" résolu ce problème.

1
Brent

essayez aussi ceci

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

dans mon cas, le serveur répond avec un caractère inconnu avant '{'

1
valir

Si renvoyer un tableau fonctionne et que renvoyer un seul objet ne fonctionne pas, vous pouvez également essayer de renvoyer votre objet unique sous la forme d'un tableau contenant cet objet unique:

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

de cette façon, vous retournez une structure de données cohérente, un tableau d'objets, quelle que soit la charge utile des données.

je vois que vous avez essayé de placer votre objet unique entre "parenthèses", et vous le suggérez avec des exemples car, bien entendu, JavaScript traite [..] différemment de (..)

1
David Alpert

Si le gestionnaire d'erreurs de jQuery est appelé et que l'objet XHR contient une "erreur d'analyse syntaxique", il s'agit probablement d'une erreur d'analyse syntaxique provenant du serveur.

Votre scénario à plusieurs résultats lorsque vous appelez le service sans paramètre est-il en train de se rompre lorsque vous essayez de fournir un paramètre permettant de récupérer l'enregistrement unique?

De quel backend retournez-vous cela?

Sur les services ASMX, par exemple, c'est souvent le cas lorsque des paramètres sont fournis à jQuery sous la forme d'un objet JSON au lieu d'une chaîne JSON. Si vous fournissez à jQuery un objet JSON réel pour son paramètre "data", il sera sérialisé dans des paires k et v standard et délimitées au lieu de l'envoyer sous forme de fichier JSON.

1
Dave Ward

jQuery étouffe certaines clés JSON. J'envoyais cet extrait JSON en PHP:

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

Renommer la clé 'résultat' en quelque chose d'autre fonctionne. J'imagine que c'est une sorte de collision de mots réservés, qui pourrait être un bogue dans jQuery (1.4.2).

1
Jonathon Hill

J'ai trouvé dans certaines de mes implémentations que je devais ajouter:

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

qui semblait résoudre le problème. Eval ou pas, il semblait faire exactement la même chose pour moi.

1
Jay

Je me débattais avec ceci et passais quelques heures à essayer de comprendre ceci, jusqu'à ce que j'utilise firebug pour montrer l'objet de données.

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