jQuery analysiert meinen JSON nicht aus der AJAX-Abfrage

88

Ich habe Probleme beim Parsen einiger von meinem Server zurückgegebener JSON-Daten mit jQuery.ajax ()

Um den AJAX auszuführen, verwende ich:

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

Und wenn ich eine Reihe von Elementen zurückgebe, funktioniert es einwandfrei:

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

Die Erfolgsfunktion wird aufgerufen und erhält das richtige Objekt.

Wenn ich jedoch versuche, ein einzelnes Objekt zurückzugeben:

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

Die Fehlerfunktion wird aufgerufen und xhr enthält 'Parsererror'. Ich habe versucht, den JSON auf dem Server in Klammern zu setzen, bevor er über das Kabel gesendet wird, aber es macht keinen Unterschied. Wenn ich den Inhalt jedoch in eine Zeichenfolge in Javascript einfüge und dann die Funktion eval () verwende, wird er perfekt ausgewertet.

Irgendwelche Ideen, was ich falsch mache?

Anthony

littlecharva
quelle
Siehe auch
Michael Myers

Antworten:

72

Sendet Ihr Server Daten als Inhaltstyp "*/json"? Wenn nicht, ändern Sie die Antwortheader entsprechend. Senden "application/json"wäre zum Beispiel in Ordnung.

Tomalak
quelle
Zweitens hatte diese Vermutung einmal das gleiche Problem und erfuhr, dass ich überraschenderweise den falschen Pantomimentyp verwendete. Wenn Sie über localhost unter Windows testen, sollten Sie sich dessen sehr bewusst sein. Versuchen Sie, es irgendwo hochzuladen und erneut zu testen. Wenn Sie möchten, dass es auf localhost funktioniert, müssen Sie die Anfrage wirklich fummeln.
Josh
51

Gemäß der Spezifikation von json.org ist Ihre Rücksendung ungültig. Die Namen werden immer in Anführungszeichen gesetzt, daher sollten Sie zurückkehren

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

und

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

Dies ist möglicherweise nicht das Problem bei Ihrem Setup, da Sie sagen, dass eines davon jetzt funktioniert. Es sollte jedoch aus Gründen der Richtigkeit behoben werden, falls Sie in Zukunft zu einem anderen JSON-Parser wechseln müssen.

Ben Combee
quelle
2
In jQuery 1.4 (zum Beispiel) { key: 'val' }ist JSON in der Tat nicht gültig.
rfunduk
34

JSON-Zeichenfolgen werden in doppelte Anführungszeichen gesetzt. einfache Anführungszeichen sind kein gültiger Ersatz.

{"who": "Hello World"}

ist gültig, aber das ist nicht ...

{'who': 'Hello World'}

Obwohl dies nicht das Problem des OP ist, hielt ich es für erwähnenswert, für andere, die hier landen.

John Mee
quelle
30

Dieses Problem ist normalerweise darauf zurückzuführen, dass Ihre Anfrage den falschen MIME-Typ erhalten hat. Wenn Sie auf Ihrem eigenen Computer entwickeln, erhalten Sie manchmal nicht den richtigen MIME-Typ vom "Server", der Ihr eigener Computer ist. Ich bin bei der Entwicklung einmal auf dieses Problem gestoßen, indem ich die lokal gespeicherte Datei im Browser geöffnet habe (z. B. lautete die URL "c: /project/test.html").

Verwenden Sie die Eigenschaft beforeSend, um eine Rückruffunktion hinzuzufügen, die den MIME-Typ überschreibt. Dadurch wird der Code dazu verleitet, mit json umzugehen, obwohl der falsche MIME-Typ vom Server gesendet und von Ihrem aufrufenden Code empfangen wird. Ein Beispielcode ist unten.

Der richtige MIME-Typ ist laut dieser Frage application / json , aber ich weiß, dass application / j-son funktioniert hat, als ich es ausprobiert habe (jetzt vor einigen Jahren). Sie sollten wahrscheinlich zuerst application / json ausprobieren.

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...
 }
});
Josh
quelle
Ich möchte nur sagen, dass der Vorschlag von beforeSend, den Sie vorschlagen, für mich funktioniert hat !! Mein Ajax-Anruf funktionierte hervorragend in Safari und Chrom, aber nicht in Firefox. Sobald ich das beforeSend hinzugefügt habe, ist Firefox sofort gestartet. Beeindruckend!! Vielen Dank!!
Karmen Blake
7

Ich hatte dieses Problem und für eine Weile habe ich verwendet

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

um die in einem Objekt zurückgegebenen Daten zu erhalten. Später gab es jedoch andere Probleme, bei denen ein Fehler in Klammern angezeigt wurde, und es wurde festgestellt, dass jQuery eine Funktion speziell zum Auswerten einer Zeichenfolge für eine JSON-Struktur hat:

$.parseJSON(data)

sollte den Trick machen. Dies ist natürlich zusätzlich zu Ihrer JSON-Zeichenfolge im richtigen Format.

Jubair
quelle
6

Wenn Sie die json-Antwort wiedergeben und Ihre Header nicht mit * / json übereinstimmen, können Sie die integrierte jQuery.parseJSON-API verwenden, um die Antwort zu analysieren.

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

Ist nicht was du denkst. Als Ausdruck ist es ein Objektliteral, aber als Aussage ist 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

Leider gibt Ihnen eval () keine Möglichkeit anzugeben, ob Sie ihm eine Aussage oder einen Ausdruck geben, und es neigt dazu, falsch zu raten.

Die übliche Lösung besteht in der Tat darin, alles in Klammern zu setzen, bevor es an die Funktion eval () gesendet wird. Sie sagen, Sie haben das auf dem Server versucht ... offensichtlich kommt das irgendwie nicht durch. Es sollte wasserdicht sein, auf Client-Seite zu sagen, was auch immer die XMLHttpRequest-Antwort empfängt:

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

anstatt:

eval(responseText);

solange die Antwort wirklich ein Ausdruck ist, keine Aussage. (z. B. enthält es keine mehrfachen, durch Semikolons oder Zeilenumbrüche getrennten Klauseln.)

Bobince
quelle
Ich denke, jQuery fügt die Klammern automatisch hinzu, wenn die Anforderungsdaten verarbeitet werden.
Strager
2
Diese Antwort war für mich sehr hilfreich, da ich nie verstanden habe, warum Leute JSON in Klammern setzen.
Andrey Tarantsov
3

Sie müssen den Inhaltstyp des Headers in Ihrem PHP wie folgt einstellen:

 <?php

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

 ?>

Sehen Sie sich dieses Video zum besseren Verständnis an ....

Referenz: http://www.youtube.com/watch?v=EvFXWqEqh6o

user3612872
quelle
2

Wenn Sie ASP.NET-Webdienste mit jQuery verwenden, stellen Sie sicher, dass in Ihrer web.config Folgendes enthalten ist:

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

Ich hatte ein ähnliches Problem wie dieses, bei dem Firefox 3.5 einwandfrei funktionierte und meine JSON-Daten analysierte, Firefox 3.0.6 jedoch einen Parsererror zurückgab. Es stellte sich heraus, dass es zu Beginn des JSON ein Leerzeichen war, das dazu führte, dass Firefox 3.0.6 einen Fehler auslöste. Durch Entfernen des Leerzeichens wurde das Problem behoben

Jonburney
quelle
2

Die Techniken "eval ()" und "JSON.parse ()" verwenden sich gegenseitig ausschließende Formate.

  • Bei "eval ()" sind Klammern erforderlich .
  • Mit "JSON.parse ()" sind Klammern verboten .

Achtung, es gibt "stringify ()" - Funktionen, die das "eval" -Format erzeugen. Für Ajax sollten Sie nur das JSON-Format verwenden.

Während "eval" die gesamte JavaScript-Sprache enthält, verwendet JSON nur eine winzige Teilmenge der Sprache. Zu den Konstrukten in der JavaScript-Sprache, die "eval" erkennen muss, gehört die "Block-Anweisung" (auch bekannt als "zusammengesetzte Anweisung") . Dies ist ein Paar oder geschweifte Klammern "{}" mit einigen Anweisungen im Inneren. Geschweifte Klammern werden aber auch in der Syntax von Objektliteralen verwendet. Die Interpretation unterscheidet sich durch den Kontext, in dem der Code erscheint. Etwas mag für Sie wie ein Objektliteral aussehen, aber "eval" sieht es als zusammengesetzte Aussage.

In der JavaScript-Sprache treten Objektliterale rechts von einer Zuweisung auf.

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

Objektliterale treten nicht alleine auf.

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

Als er auf die ursprüngliche Frage des OP zurückging, die 2008 gestellt wurde, fragte er, warum in "eval ()" Folgendes fehlschlägt:

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

Die Antwort ist, dass es wie eine zusammengesetzte Aussage aussieht. Um es in ein Objekt zu konvertieren, müssen Sie es in einen Kontext stellen, in dem eine zusammengesetzte Anweisung nicht möglich ist. Dies geschieht durch Klammern

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

Die OP fragte auch , warum eine ähnliche Aussage tat erfolgreich eval:

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

Die gleiche Antwort gilt - die geschweiften Klammern befinden sich in einem Kontext, in dem eine zusammengesetzte Aussage unmöglich ist. Dies ist ein Array-Kontext " [...]", und Arrays können Objekte enthalten, aber keine Anweisungen.

Im Gegensatz zu "eval ()" sind die Funktionen von JSON sehr eingeschränkt. Die Einschränkung ist beabsichtigt. Der Designer von JSON beabsichtigte eine minimalistische Teilmenge von JavaScript, wobei nur die Syntax verwendet wurde, die auf der rechten Seite einer Zuweisung angezeigt werden konnte. Wenn Sie also Code haben, der in JSON korrekt analysiert wird ...

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

... das bedeutet, dass es auch auf der rechten Seite eines Auftrags wie diesem legal analysiert wird.

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

Dies ist jedoch nicht die einzige Einschränkung für JSON. Die BNF-Sprachspezifikation für JSON ist sehr einfach. Beispielsweise ist die Verwendung von einfachen Anführungszeichen zur Angabe von Zeichenfolgen nicht zulässig (wie dies bei JavaScript und Perl der Fall ist), und es ist nicht möglich, ein einzelnes Zeichen als Byte auszudrücken (wie dies bei 'C' der Fall ist). Leider sind auch keine Kommentare zulässig (was beim Erstellen von Konfigurationsdateien sehr hilfreich wäre). Der Vorteil all dieser Einschränkungen ist, dass das Parsen von JSON schnell ist und keine Möglichkeit zur Code-Injection bietet (eine Sicherheitsbedrohung).

Aufgrund dieser Einschränkungen kann JSON keine Klammern verwenden. Folglich ist eine Klammer in einer JSON-Zeichenfolge ein unzulässiges Zeichen.

Verwenden Sie aus folgenden Gründen immer das JSON-Format mit Ajax:

  • Eine typische Ajax-Pipeline wird für JSON konfiguriert.
  • Die Verwendung von "eval ()" wird als Sicherheitsrisiko kritisiert.

Betrachten Sie als Beispiel für eine Ajax-Pipeline ein Programm, an dem ein Knotenserver und ein jQuery-Client beteiligt sind. Das Client-Programm verwendet einen jQuery-Aufruf mit dem Formular $.ajax({dataType:'json',...etc.});. JQuery erstellt ein jqXHR-Objekt zur späteren Verwendung, verpackt und sendet die zugehörige Anforderung. Der Server akzeptiert die Anforderung, verarbeitet sie und ist dann bereit zu antworten. Das Serverprogramm ruft die Methode res.json(data)zum Packen und Senden der Antwort auf. Zurück auf der Clientseite akzeptiert jQuery die Antwort, konsultiert das zugehörige jqXHR-Objekt und verarbeitet die JSON-formatierten Daten. Dies alles funktioniert ohne manuelle Datenkonvertierung. Die Antwort beinhaltet keinen expliziten Aufruf von JSON.stringify () auf dem Knotenserver und keinen expliziten Aufruf von JSON.parse () auf dem Client. das ist alles für dich erledigt.

Die Verwendung von "eval" ist mit Sicherheitsrisiken für die Code-Injektion verbunden. Sie könnten denken, dass es keinen Weg gibt, der passieren kann, aber Hacker können ziemlich kreativ werden. Außerdem ist "eval" für die Javascript-Optimierung problematisch.

Wenn Sie eine "stringify ()" - Funktion verwenden, beachten Sie, dass einige Funktionen mit diesem Namen Zeichenfolgen erstellen, die mit "eval" und nicht mit JSON kompatibel sind. In Node erhalten Sie beispielsweise die folgende Funktion, mit der Zeichenfolgen im "eval" -kompatiblen Format erstellt werden:

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

Dies kann nützlich sein, aber wenn Sie keinen bestimmten Bedarf haben, ist es wahrscheinlich nicht das, was Sie wollen.

IAM_AL_X
quelle
1

Wenn die Rückgabe eines Arrays funktioniert und die Rückgabe eines einzelnen Objekts nicht funktioniert, können Sie auch versuchen, Ihr einzelnes Objekt als Array zurückzugeben, das dieses einzelne Objekt enthält:

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

Auf diese Weise geben Sie eine konsistente Datenstruktur zurück, ein Array von Objekten, unabhängig von der Datennutzlast.

Ich sehe, dass Sie versucht haben, Ihr einzelnes Objekt in "Klammern" zu verpacken, und schlage dies mit einem Beispiel vor, da JavaScript [..] natürlich anders behandelt als (..)

David Alpert
quelle
1

Wenn der Fehlerhandler von jQuery aufgerufen wird und das XHR-Objekt "Parserfehler" enthält, handelt es sich wahrscheinlich um einen Parserfehler, der vom Server zurückkommt.

Ist Ihr Szenario mit mehreren Ergebnissen, wenn Sie den Dienst ohne Parameter aufrufen, aber es bricht ab, wenn Sie versuchen, einen Parameter zum Abrufen des einzelnen Datensatzes anzugeben?

Von welchem ​​Backend geben Sie das zurück?

Bei ASMX-Diensten ist dies beispielsweise häufig der Fall, wenn Parameter an jQuery als JSON-Objekt anstelle einer JSON-Zeichenfolge übergeben werden. Wenn Sie jQuery ein tatsächliches JSON-Objekt für seinen "Daten" -Parameter bereitstellen, wird dieses in standardmäßige und begrenzte k, v-Paare serialisiert, anstatt es als JSON zu senden.

Dave Ward
quelle
1

Ich fand in einigen meiner Implementierungen, die ich hinzufügen musste:

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

das schien das Problem zu lösen. Eval oder nicht, es schien genau das gleiche für mich zu tun.

Jay
quelle
Verwenden Sie das Objektliteral, wenn Sie ein neues Objekt initialisieren, nicht den Objektkonstruktor: var obj = {};
Andreas Grech
Ja, ich verstehe, var myArray = [] für Arrays und var myObject = {}, danke für den Tipp Dreas
Jay
1

jQuery drosselt bestimmte JSON-Schlüssel. Ich habe dieses JSON-Snippet in PHP gesendet:

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

Das Umbenennen des Ergebnisschlüssels in etwas anderes funktioniert. Ich würde vermuten, dass dies eine reservierte Wortkollision ist und ein Fehler in jQuery (1.4.2) sein könnte.

Jonathon Hill
quelle
1

In einer ColdFusion-Umgebung ist es eine Sache, die selbst bei wohlgeformtem JSON zu einem Fehler führt, wenn im ColdFusion-Administrator die Option "Anforderungs-Debugging-Ausgabe aktivieren" aktiviert ist (unter Debugging & Protokollierung> Debug-Ausgabeeinstellungen). Debugging-Informationen werden mit den JSON-Daten zurückgegeben und machen sie somit ungültig.

Dave DuPlantis
quelle
1

versuchen Sie auch dies

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

In meinem Fall antwortet der Server mit einem unbekannten Zeichen vor '{'

Valir
quelle
1

Ich habe status = parseerror und xhr.status = 200 erhalten.

Das Problem für mich war, dass die URLs in der JSON-Antwort durch '\' Umschalten auf '/' behoben wurden.

Brent
quelle
0

Ich hatte damit zu kämpfen und verbrachte einige Stunden damit, dies herauszufinden, bis ich Firebug verwendete, um das Datenobjekt anzuzeigen.

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

verwenden

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

auf der Serverseite. Verwenden Sie auf der Clientseite Ajax mit Datentyp JSON und stellen Sie sicher, dass Ihre Dokumentcodierung nicht UTF-8 mit Stückliste ist, sondern UTF-8.

user2854865
quelle