jQuery non analizzerà il mio JSON dalla query AJAX


88

Ho difficoltà ad analizzare alcuni dati JSON restituiti dal mio server utilizzando jQuery.ajax ()

Per eseguire l'AJAX che sto usando:

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

E se restituisco una serie di articoli, funziona bene:

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

La funzione success viene chiamata e riceve l'oggetto corretto.

Tuttavia, quando provo a restituire un singolo oggetto:

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

Viene chiamata la funzione di errore e xhr contiene "parsererror". Ho provato a racchiudere il JSON tra parentesi sul server prima di inviarlo in rete, ma non fa differenza. Tuttavia, se incollo il contenuto in una stringa in Javascript e poi utilizzo la funzione eval (), lo valuta perfettamente.

Qualche idea su cosa sto sbagliando?

Anthony


Risposte:


72

Il tuo server invia dati come Content-Type "*/json"? In caso contrario, modificare le intestazioni della risposta di conseguenza. L'invio "application/json"andrebbe bene, per esempio.


Secondo questa ipotesi, ho avuto lo stesso problema una volta e ho imparato che sorprendentemente stavo usando il tipo MIME sbagliato. Se stai testando su localhost su Windows, tienilo molto presente. Prova a caricarlo da qualche parte e testalo di nuovo. Se vuoi che funzioni su localhost devi davvero confondere la richiesta.
Josh

51

Secondo la specifica json.org , il tuo reso non è valido. I nomi sono sempre citati, quindi dovresti tornare

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

e

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

Questo potrebbe non essere il problema con la tua configurazione, dal momento che dici che uno di loro funziona ora, ma dovrebbe essere corretto per correttezza nel caso in cui sia necessario passare a un altro parser JSON in futuro.


2
In effetti, in jQuery 1.4 (ad esempio) { key: 'val' }non è valido JSON.
rfunduk

34

Le stringhe JSON sono racchiuse tra virgolette doppie ; virgolette singole non sono un valido sostituto.

{"who": "Hello World"}

è valido ma non lo è ...

{'who': 'Hello World'}

Sebbene non sia un problema dell'OP, ho pensato che valesse la pena notare per gli altri che atterrano qui.


30

Questo problema è solitamente dovuto al fatto che la tua richiesta ha ricevuto il tipo MIME sbagliato. Quando si sviluppa sul proprio computer, a volte non si riceve il tipo MIME appropriato dal "server", che è il proprio computer. Mi sono imbattuto in questo problema una volta durante lo sviluppo aprendo il file memorizzato localmente nel browser (ad esempio, l'URL era "c: /project/test.html").

Prova a utilizzare la proprietà beforeSend per aggiungere una funzione di callback che sostituisce il tipo MIME. Ciò indurrà il codice a gestire json nonostante il tipo MIME errato sia stato inviato dal server e ricevuto dal codice chiamante. Di seguito è riportato un codice di esempio.

Il tipo MIME corretto è application / json in base a questa domanda , ma so che application / j-son ha funzionato quando l'ho provato (ora diversi anni fa). Probabilmente dovresti provare prima 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...
 }
});

Voglio solo dire che il suggerimento prima di inviare che suggerisci ha funzionato per me !! la mia chiamata ajax ha funzionato alla grande in Safari e Chrome ma non in Firefox. non appena ho aggiunto il beforeSend, Firefox è partito subito. Wow!! Grazie!!
Karmen Blake

7

Ho avuto questo problema e per un po 'ho usato

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

per ottenere i dati restituiti in un oggetto. ma in seguito ha avuto altri problemi a ottenere un errore `` mancante) tra parentesi 'e ha scoperto che jQuery ha una funzione specifica per valutare una stringa per una struttura json:

$.parseJSON(data)

dovrebbe fare il trucco. Questo è in aggiunta ad avere la tua stringa json nel formato corretto, ovviamente ..


6

Se stai eseguendo l'eco della risposta json e le tue intestazioni non corrispondono * / json, puoi utilizzare l'API jQuery.parseJSON incorporata per analizzare la risposta.

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

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

Non è quello che pensi. Come espressione, è un oggetto letterale, ma come dichiarazione è:

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

Sfortunatamente eval () non ti dà un modo per specificare se gli stai dando un'istruzione o un'espressione e tende a indovinare in modo sbagliato.

La solita soluzione è infatti racchiudere qualsiasi cosa tra parentesi prima di inviarlo alla funzione eval (). Dici di averlo provato sul server ... chiaramente in qualche modo non riesce. Dovrebbe essere impermeabile da dire sul lato client, qualunque cosa riceva la risposta XMLHttpRequest:

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

invece di:

eval(responseText);

fintanto che la risposta è davvero un'espressione non un'affermazione. (ad es. non ha più clausole separate da punto e virgola o da nuova riga.)


Penso che jQuery aggiunga automaticamente le parentesi durante l'elaborazione dei dati della richiesta.
Strager

2
Questa risposta è stata molto utile per me, poiché non ho mai capito perché le persone racchiudono JSON tra parentesi.
Andrey Tarantsov


2

Se stai consumando servizi Web ASP.NET utilizzando jQuery, assicurati di avere quanto segue incluso nel tuo web.config:

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

2

Ho avuto un problema simile a questo in cui Firefox 3.5 ha funzionato bene e ha analizzato i miei dati JSON ma Firefox 3.0.6 ha restituito un parseerror. Si è scoperto che era uno spazio vuoto all'inizio del JSON che ha causato l'errore di Firefox 3.0.6. La rimozione dello spazio vuoto lo ha risolto


2

Le tecniche "eval ()" e "JSON.parse ()" utilizzano formati che si escludono a vicenda.

  • Con "eval ()" le parentesi sono obbligatorie .
  • Con "JSON.parse ()" le parentesi sono vietate .

Attenzione, ci sono funzioni "stringify ()" che producono il formato "eval". Per ajax, dovresti usare solo il formato JSON.

Sebbene "eval" incorpori l'intero linguaggio JavaScript, JSON utilizza solo un piccolo sottoinsieme del linguaggio. Tra i costrutti nel linguaggio JavaScript che "eval" deve riconoscere è l ' "istruzione Block" ( nota anche come "istruzione composta") ; che è una coppia o parentesi graffe "{}" con alcune istruzioni all'interno. Ma le parentesi graffe vengono utilizzate anche nella sintassi dei letterali oggetto. L'interpretazione è differenziata dal contesto in cui compare il codice. Qualcosa potrebbe sembrarti un oggetto letterale, ma "eval" lo vedrà come un'istruzione composta.

Nel linguaggio JavaScript, i valori letterali degli oggetti si trovano a destra di un compito.

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

I letterali oggetto non si verificano da soli.

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

Tornando alla domanda originale dell'OP, posta nel 2008, ha chiesto perché quanto segue fallisce in "eval ()":

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

La risposta è che sembra un'affermazione composta. Per convertirlo in un oggetto, è necessario inserirlo in un contesto in cui un'istruzione composta è impossibile. Ciò viene fatto inserendovi una parentesi

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

L'OP ha anche chiesto perché un'affermazione simile abbia avuto successo:

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

La stessa risposta si applica: le parentesi graffe sono in un contesto in cui un'istruzione composta è impossibile. Questo è un contesto di array, " [...]" e gli array possono contenere oggetti, ma non possono contenere istruzioni.

A differenza di "eval ()", JSON è molto limitato nelle sue capacità. La limitazione è intenzionale. Il progettista di JSON intendeva un sottoinsieme minimalista di JavaScript, utilizzando solo la sintassi che potrebbe apparire sul lato destro di un compito. Quindi, se hai del codice che analizza correttamente in JSON ...

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

... ciò implica che analizzerà legalmente anche sul lato destro di un compito, come questo ..

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

Ma questa non è l'unica restrizione su JSON. La specifica del linguaggio BNF per JSON è molto semplice. Ad esempio, non consente l'uso di virgolette singole per indicare stringhe (come fanno JavaScript e Perl) e non ha un modo per esprimere un singolo carattere come byte (come fa 'C'). Sfortunatamente, inoltre, non consente commenti (il che sarebbe davvero bello quando si creano file di configurazione). Il vantaggio di tutte queste limitazioni è che l'analisi di JSON è veloce e non offre alcuna possibilità di iniezione di codice (una minaccia per la sicurezza).

A causa di queste limitazioni, JSON non può utilizzare le parentesi. Di conseguenza, una parentesi in una stringa JSON è un carattere illegale.

Usa sempre il formato JSON con ajax, per i seguenti motivi:

  • Una tipica pipeline ajax verrà configurata per JSON.
  • L'uso di "eval ()" sarà criticato come un rischio per la sicurezza.

Come esempio di una pipeline ajax, considera un programma che coinvolge un server Node e un client jQuery. Il programma client utilizza una chiamata jQuery avente il modulo $.ajax({dataType:'json',...etc.});. JQuery crea un oggetto jqXHR per un uso successivo, quindi crea un pacchetto e invia la richiesta associata. Il server accetta la richiesta, la elabora e quindi è pronto a rispondere. Il programma server chiamerà il metodo res.json(data)per creare il pacchetto e inviare la risposta. Tornando al lato client, jQuery accetta la risposta, consulta l'oggetto jqXHR associato ed elabora i dati formattati JSON. Tutto questo funziona senza alcuna necessità di conversione manuale dei dati. La risposta non implica alcuna chiamata esplicita a JSON.stringify () sul server Node e nessuna chiamata esplicita a JSON.parse () sul client; è tutto gestito per te.

L'utilizzo di "eval" è associato ai rischi per la sicurezza dell'iniezione di codice. Potresti pensare che non sia possibile, ma gli hacker possono diventare piuttosto creativi. Inoltre, "eval" è problematico per l'ottimizzazione Javascript.

Se ti ritrovi a utilizzare una funzione "stringify ()", tieni presente che alcune funzioni con quel nome creeranno stringhe compatibili con "eval" e non con JSON. Ad esempio, in Node, quanto segue fornisce una funzione che crea stringhe in formato compatibile "eval":

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

Questo può essere utile, ma a meno che tu non abbia un'esigenza specifica, probabilmente non è quello che vuoi.


1

Se la restituzione di un array funziona e la restituzione di un singolo oggetto no, potresti anche provare a restituire il tuo singolo oggetto come un array contenente quel singolo oggetto:

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

in questo modo restituisci una struttura dati coerente, un array di oggetti, indipendentemente dal carico utile dei dati.

vedo che hai provato a racchiudere il tuo singolo oggetto tra "parentesi" e suggeriscilo con un esempio perché ovviamente JavaScript tratta [..] in modo diverso da (..)


1

Se il gestore degli errori di jQuery viene chiamato e l'oggetto XHR contiene "errore del parser", è probabilmente un errore del parser che torna dal server.

Il tuo scenario con più risultati è quando chiami il servizio senza un parametro, ma si interrompe quando provi a fornire un parametro per recuperare il singolo record?

Da quale backend lo stai restituendo?

Sui servizi ASMX, ad esempio, è spesso il caso in cui i parametri vengono forniti a jQuery come oggetto JSON anziché come stringa JSON. Se fornisci a jQuery un oggetto JSON effettivo per il suo parametro "data", lo serializzerà in coppie k, v standard e delimitate invece di inviarlo come JSON.


1

Ho trovato in alcune delle mie implementazioni che dovevo aggiungere:

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

che sembrava risolvere il problema. Eval o no sembrava fare esattamente lo stesso per me.


Utilizza il valore letterale oggetto quando inizializza un nuovo oggetto, non il costruttore Object: var obj = {};
Andreas Grech

Sì, capisco, var myArray = [] per array e var myObject = {}, grazie per il suggerimento Dreas
Jay

1

jQuery si blocca su alcune chiavi JSON. Stavo inviando questo snippet JSON in PHP:

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

Rinominare la chiave "risultato" in qualcos'altro funziona. Immagino che questa sia una collisione di parole riservate di qualche tipo e potrebbe essere un bug in jQuery (1.4.2).


1

In un ambiente ColdFusion, una cosa che causerà un errore, anche con JSON ben formato, è l' attivazione dell'output di debug delle richieste nell'amministratore di ColdFusion (in Debug e registrazione> Impostazioni dell'output di debug). Le informazioni di debug verranno restituite con i dati JSON e quindi le renderanno non valide.


1

prova anche questo

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

nel mio caso il server risponde con un carattere sconosciuto prima di "{"


1

Stavo ottenendo status = parseerror e xhr.status = 200.

Il problema per me era che l'URL all'interno della risposta JSON aveva risolto il problema con "\" passando a "/".


0

Stavo lottando con questo e ho passato alcune ore a cercare di capirlo, finché non ho usato Firebug per mostrare l'oggetto dati.

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

-1

uso

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

lato server. Sul lato client usa ajax con Datatype JSON e assicurati che la codifica del tuo documento non sia UTF-8 con BOM deve essere UTF-8.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.