jQuery nie przeanalizuje mojego kodu JSON z zapytania AJAX


88

Mam trudności z analizowaniem niektórych danych JSON zwróconych z mojego serwera za pomocą jQuery.ajax ()

Aby wykonać AJAX, którego używam:

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

A jeśli zwrócę tablicę elementów, to działa dobrze:

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

Funkcja sukcesu jest wywoływana i otrzymuje prawidłowy obiekt.

Jednak gdy próbuję zwrócić pojedynczy obiekt:

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

Wywoływana jest funkcja błędu, a xhr zawiera „parsererror”. Próbowałem zawinąć JSON w nawias na serwerze przed wysłaniem go dalej, ale to nie robi różnicy. Jednak jeśli wkleię zawartość do ciągu znaków w JavaScript, a następnie użyję funkcji eval (), oceni ją doskonale.

Jakieś pomysły, co robię źle?

Anthony


Odpowiedzi:


72

Czy Twój serwer wysyła dane jako typ zawartości "*/json"? Jeśli nie, odpowiednio zmodyfikuj nagłówki odpowiedzi. Na przykład wysyłanie "application/json"byłoby w porządku.


Po drugie, miałem ten sam problem i dowiedziałem się, że o dziwo używam niewłaściwego typu mime. Jeśli testujesz przez localhost w systemie Windows, bądź tego świadomy. Spróbuj przesłać go gdzieś i przetestuj ponownie. Jeśli chcesz, aby działał na hoście lokalnym, musisz naprawdę sfałszować żądanie.
Josh

51

Zgodnie ze specyfikacją json.org Twój zwrot jest nieprawidłowy. Imiona są zawsze cytowane, więc powinieneś wracać

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

i

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

Może to nie być problem z twoją konfiguracją, ponieważ mówisz, że jeden z nich działa teraz, ale powinien zostać naprawiony pod kątem poprawności na wypadek konieczności przełączenia się na inny parser JSON w przyszłości.


2
Rzeczywiście, w jQuery 1.4 (na przykład) { key: 'val' }nie jest poprawnym JSON.
rfunduk

34

Ciągi JSON są zawijane w podwójne cudzysłowy; apostrofy nie są prawidłowym zamiennikiem.

{"who": "Hello World"}

jest ważne, ale to nie jest ...

{'who': 'Hello World'}

Chociaż nie jest to kwestia PO, pomyśleliśmy, że warto zwrócić uwagę na innych, którzy tu lądują.


30

Ten problem jest zwykle spowodowany tym, że żądanie otrzymało niewłaściwy typ MIME. Podczas programowania na własnym komputerze, czasami nie otrzymujesz odpowiedniego typu MIME z „serwera”, którym jest Twój własny komputer. Kiedyś napotkałem ten problem podczas programowania, otwierając lokalnie przechowywany plik w przeglądarce (np. Adres URL to „c: /project/test.html”).

Spróbuj użyć właściwości beforeSend, aby dodać funkcję zwrotną, która zastępuje typ MIME. Spowoduje to, że kod poradzi sobie z json pomimo wysłania przez serwer niewłaściwego typu MIME i odebrania go przez kod wywołujący. Poniżej znajduje się przykładowy kod.

Odpowiedni typ mime to application / json zgodnie z tym pytaniem , ale wiem, że application / j-son działał, kiedy go wypróbowałem (teraz kilka lat temu). Prawdopodobnie powinieneś najpierw wypróbować 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...
 }
});

chcę tylko powiedzieć, że sugestia beforeSend, którą sugerujesz, zadziałała dla mnie !! moje wywołanie Ajax działało świetnie w Safari i Chrome, ale nie w Firefoksie. jak tylko dodałem beforeSend, wtedy Firefox ruszył. łał!! Dzięki!!
Karmen Blake

7

Miałem ten problem i przez jakiś czas korzystałem

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

aby uzyskać dane zwrócone w obiekcie. ale później wystąpiły inne problemy z błędem `` brakujący) w nawiasach i okazało się, że jQuery ma funkcję przeznaczoną specjalnie do oceny ciągu dla struktury json:

$.parseJSON(data)

powinien załatwić sprawę. Jest to oczywiście dodatek do posiadania łańcucha json w odpowiednim formacie.


6

Jeśli odbierasz odpowiedź json, a nagłówki nie są zgodne * / json, możesz użyć wbudowanego interfejsu API jQuery.parseJSON do przeanalizowania odpowiedzi.

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

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

Nie jest tym, co myślisz. Jako wyrażenie jest to literał Object, ale jako instrukcja jest to:

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

Niestety eval () nie daje możliwości określenia, czy podajesz instrukcję, czy wyrażenie, i ma tendencję do błędnego odgadywania.

Zwykłym rozwiązaniem jest rzeczywiście zawijanie czegokolwiek w nawiasach przed wysłaniem tego do funkcji eval (). Mówisz, że próbowałeś tego na serwerze ... najwyraźniej jakoś to się nie udaje. Powinien być wodoodporny, aby powiedzieć po stronie klienta, cokolwiek otrzymuje odpowiedź XMLHttpRequest:

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

zamiast:

eval(responseText);

o ile odpowiedź jest rzeczywiście wyrażeniem, a nie stwierdzeniem. (np. nie zawiera wielu klauzul oddzielonych średnikiem lub znakiem nowej linii).


Myślę, że jQuery automatycznie dodaje nawiasy podczas przetwarzania danych żądania.
strager

2
Ta odpowiedź była dla mnie bardzo pomocna, ponieważ nigdy nie rozumiałem, dlaczego ludzie umieszczają JSON w nawiasach.
Andrey Tarantsov


2

Jeśli korzystasz z usług sieci Web ASP.NET przy użyciu jQuery, upewnij się, że plik web.config zawiera następujące elementy:

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

2

Miałem podobny problem do tego, w którym Firefox 3.5 działał dobrze i przeanalizował moje dane JSON, ale Firefox 3.0.6 zwrócił parseerror. Okazało się, że to puste miejsce na początku JSON spowodowało, że Firefox 3.0.6 wyrzucił błąd. Usunięcie pustej przestrzeni naprawiło to


2

Techniki „eval ()” i „JSON.parse ()” wykorzystują wzajemnie wykluczające się formaty.

  • Z nawiasami „eval ()” są wymagane .
  • W nawiasach „JSON.parse ()” nie wolno używać nawiasów .

Uwaga, istnieją funkcje „stringify ()”, które generują format „eval”. W przypadku AJAX należy używać tylko formatu JSON.

Podczas gdy „eval” obejmuje cały język JavaScript, JSON wykorzystuje tylko niewielki podzbiór języka. Wśród konstrukcji w języku JavaScript, które „eval” musi rozpoznać, jest „Instrukcja blokowa” (inaczej „instrukcja złożona”) ; który jest parą lub nawiasami klamrowymi „{}” z pewnymi instrukcjami w środku. Ale nawiasy klamrowe są również używane w składni literałów obiektowych. Interpretację różnicuje kontekst, w którym pojawia się kod. Coś może wyglądać jak obiekt dosłowny, ale „eval” zobaczy to jako instrukcję złożoną.

W języku JavaScript literały obiektowe pojawiają się po prawej stronie przypisania.

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

Literały obiektów nie występują samodzielnie.

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

Wracając do pierwotnego pytania OP, zadanego w 2008 r., Zapytał, dlaczego w „eval ()” nie powiodło się następujące pytanie:

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

Odpowiedź brzmi, że wygląda to jak instrukcja złożona. Aby przekształcić go w obiekt, należy umieścić go w kontekście, w którym instrukcja złożona jest niemożliwa. Odbywa się to poprzez umieszczenie wokół niego nawiasów

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

PO zwróciła się także dlaczego podobna wypowiedź zrobiła powodzeniem eval:

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

Ta sama odpowiedź ma zastosowanie - nawiasy klamrowe znajdują się w kontekście, w którym instrukcja złożona jest niemożliwa. To jest kontekst tablicy, " [...]", a tablice mogą zawierać obiekty, ale nie mogą zawierać instrukcji.

W przeciwieństwie do „eval ()”, JSON ma bardzo ograniczone możliwości. Ograniczenie jest zamierzone. Projektant JSON miał na myśli minimalistyczny podzbiór JavaScript, używając tylko składni, która może pojawić się po prawej stronie zadania. Więc jeśli masz kod, który poprawnie analizuje w JSON ...

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

... co oznacza, że ​​zgodnie z prawem przeanalizuje również prawą stronę zadania, w ten sposób ...

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

Ale to nie jedyne ograniczenie JSON. Specyfikacja języka BNF dla JSON jest bardzo prosta. Na przykład nie pozwala na użycie pojedynczych cudzysłowów do wskazania łańcuchów (jak JavaScript i Perl) i nie ma sposobu na wyrażenie pojedynczego znaku jako bajtu (jak robi to „C”). Niestety nie pozwala również na komentarze (co byłoby bardzo fajne przy tworzeniu plików konfiguracyjnych). Zaletą wszystkich tych ograniczeń jest to, że analizowanie JSON jest szybkie i nie daje możliwości wstrzyknięcia kodu (zagrożenie bezpieczeństwa).

Z powodu tych ograniczeń JSON nie ma zastosowania w nawiasach. W rezultacie nawias w ciągu JSON jest niedozwolonym znakiem.

Zawsze używaj formatu JSON z ajaxem, z następujących powodów:

  • Typowy potok ajax zostanie skonfigurowany dla JSON.
  • Użycie metody „eval ()” będzie krytykowane jako zagrożenie bezpieczeństwa.

Jako przykład potoku Ajax rozważmy program, który obejmuje serwer Node i klienta jQuery. Program klienta używa wywołania jQuery o postaci $.ajax({dataType:'json',...etc.});. JQuery tworzy obiekt jqXHR do późniejszego użycia, a następnie pakuje i wysyła powiązane żądanie. Serwer przyjmuje żądanie, przetwarza je i jest gotowy do odpowiedzi. Program serwera wywoła metodę w res.json(data)celu spakowania i wyśle ​​odpowiedź. Po stronie klienta jQuery akceptuje odpowiedź, konsultuje się z powiązanym obiektem jqXHR i przetwarza dane w formacie JSON. To wszystko działa bez konieczności ręcznej konwersji danych. Odpowiedź nie zawiera jawnego wywołania JSON.stringify () na serwerze Node ani jawnego wywołania JSON.parse () na kliencie; to wszystko załatwiamy za Ciebie.

Użycie „eval” wiąże się z zagrożeniami bezpieczeństwa polegającymi na wstrzykiwaniu kodu. Możesz pomyśleć, że nie ma takiej możliwości, ale hakerzy mogą być całkiem kreatywni. Również „eval” jest problematyczne dla optymalizacji Javascript.

Jeśli zauważysz, że korzystasz z funkcji „stringify ()”, pamiętaj, że niektóre funkcje o tej nazwie utworzą ciągi zgodne z „eval”, a nie z JSON. Na przykład, w Node, poniżej przedstawiono funkcję, która tworzy ciągi znaków w formacie zgodnym z „eval”:

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

Może to być przydatne, ale jeśli nie masz konkretnej potrzeby, prawdopodobnie nie jest to to, czego chcesz.


1

Jeśli zwrócenie tablicy działa, a zwrócenie pojedynczego obiektu nie, możesz również spróbować zwrócić pojedynczy obiekt jako tablicę zawierającą ten pojedynczy obiekt:

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

w ten sposób zwracasz spójną strukturę danych, tablicę obiektów, bez względu na ładunek danych.

Widzę, że próbowałeś opakować swój pojedynczy obiekt w nawias i sugeruję to na przykładzie, ponieważ oczywiście JavaScript traktuje [..] inaczej niż (..)


1

Jeśli wywoływana jest procedura obsługi błędów jQuery, a obiekt XHR zawiera „błąd parsera”, prawdopodobnie jest to błąd parsera wracający z serwera.

Czy Twój scenariusz z wieloma wynikami wywołuje usługę bez parametru, ale przerywa się, gdy próbujesz podać parametr w celu pobrania pojedynczego rekordu?

Z jakiego zaplecza zwracasz to?

Na przykład w usługach ASMX dzieje się tak często, gdy parametry są dostarczane do jQuery jako obiekt JSON zamiast ciągu JSON. Jeśli podasz jQuery rzeczywisty obiekt JSON dla jego parametru „data”, zostanie on serializowany do standardowych i rozdzielanych par k, v zamiast wysyłać go jako JSON.


1

W niektórych swoich wdrożeniach znalazłem:

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

co wydawało się rozwiązać problem. Eval czy nie, wydawało mi się, że robi dokładnie to samo dla mnie.


Użyj literału obiektu podczas inicjowania nowego obiektu, a nie konstruktora Object: var obj = {};
Andreas Grech

Tak, widzę, var myArray = [] dla tablic i var myObject = {}, dzięki za wskazówkę Dreas
Jay

1

jQuery dławi się na niektórych kluczach JSON. Wysyłałem ten fragment kodu JSON w PHP:

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

Zmiana nazwy klucza „wynik” na coś innego działa. Wydaje mi się, że jest to jakiś rodzaj kolizji słów zastrzeżonych i może to być błąd w jQuery (1.4.2).


1

W środowisku ColdFusion jedyną rzeczą, która spowoduje błąd, nawet przy poprawnie sformułowanym formacie JSON, jest włączenie opcji Włącz żądanie debugowania w module Administrator ColdFusion (w sekcji Debugowanie i rejestrowanie> Ustawienia wyjścia debugowania). Informacje debugowania zostaną zwrócone wraz z danymi JSON, co spowoduje, że będą nieprawidłowe.


1

też spróbuj tego

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

w moim przypadku serwer odpowiada nieznanym znakiem przed '{'


1

Otrzymywałem status = parseerror i xhr.status = 200.

Problem polegał na tym, że adres URL w odpowiedzi JSON miał '\' przełączenie na '/' naprawione.


0

Walczyłem z tym i spędziłem kilka godzin próbując to rozgryźć, aż użyłem firebuga do pokazania obiektu danych.

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

-1

posługiwać się

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

po stronie serwera. Po stronie klienta użyj ajax z typem danych JSON i upewnij się, że kodowanie twojego dokumentu nie jest UTF-8 z BOM, musi to być UTF-8.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.