jQuery tidak akan mengurai JSON saya dari kueri AJAX


88

Saya mengalami kesulitan mengurai beberapa data JSON yang dikembalikan dari server saya menggunakan jQuery.ajax ()

Untuk melakukan AJAX yang saya gunakan:

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

Dan jika saya mengembalikan array item maka itu berfungsi dengan baik:

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

Fungsi sukses dipanggil dan menerima objek yang benar.

Namun, ketika saya mencoba mengembalikan satu objek:

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

Fungsi kesalahan dipanggil dan xhr berisi 'parsererror'. Saya sudah mencoba membungkus JSON dalam tanda kurung di server sebelum mengirimkannya ke kabel, tetapi tidak ada bedanya. Namun jika saya menempelkan konten ke dalam string di Javascript dan kemudian menggunakan fungsi eval (), itu mengevaluasi dengan sempurna.

Ada ide apa yang saya lakukan salah?

Anthony


Jawaban:


72

Apakah server Anda mengirim data sebagai Jenis Konten "*/json"? Jika tidak, ubah tajuk tanggapan yang sesuai. Mengirim "application/json"akan baik-baik saja, misalnya.


Kedua tebakan ini, pernah mengalami masalah yang sama dan mengetahui bahwa secara mengejutkan saya menggunakan jenis pantomim yang salah. Jika Anda menguji melalui localhost di windows, berhati-hatilah dengan ini. Coba unggah di suatu tempat dan uji lagi. Jika Anda ingin berfungsi di localhost, Anda harus benar-benar memalsukan permintaan.
Josh

51

Menurut spesifikasi json.org , pengembalian Anda tidak valid. Nama selalu dikutip, jadi Anda harus kembali

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

dan

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

Ini mungkin bukan masalah dengan penyiapan Anda, karena Anda mengatakan salah satunya berfungsi sekarang, tetapi itu harus diperbaiki untuk kebenaran jika Anda perlu beralih ke parser JSON lain di masa mendatang.


2
Memang, di jQuery 1.4 (misalnya) { key: 'val' }JSON tidak valid.
rfunduk

34

String JSON dibungkus dengan tanda kutip ganda ; tanda kutip tunggal bukanlah pengganti yang valid.

{"who": "Hello World"}

valid tapi ini tidak ...

{'who': 'Hello World'}

Meskipun bukan masalah OP, pikir itu perlu diperhatikan untuk orang lain yang mendarat di sini.


30

Masalah ini biasanya karena permintaan Anda menerima jenis pantomim yang salah. Saat mengembangkan di komputer Anda sendiri, terkadang Anda tidak menerima jenis mime yang tepat dari "server", yaitu komputer Anda sendiri. Saya mengalami masalah ini sekali saat mengembangkan dengan membuka file yang disimpan secara lokal di browser (mis. Url-nya adalah "c: /project/test.html").

Coba gunakan properti beforeSend untuk menambahkan fungsi callback yang menggantikan jenis mime. Ini akan mengelabui kode agar berurusan dengan json meskipun jenis mime yang salah dikirim oleh server dan diterima oleh kode panggilan Anda. Beberapa contoh kode ada di bawah.

Jenis pantomim yang tepat adalah application / json menurut pertanyaan ini , tetapi saya tahu bahwa aplikasi / j-son berfungsi ketika saya mencobanya (sekarang beberapa tahun yang lalu). Anda mungkin harus mencoba application / json terlebih dahulu.

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

hanya ingin mengatakan bahwa saran beforeSend yang Anda sarankan bekerja untuk saya !! panggilan ajax saya berfungsi dengan baik di safari dan chrome tetapi tidak firefox. segera setelah saya menambahkan beforeSend maka Firefox langsung dijalankan. Wow!! Terima kasih!!
Karmen Blake

7

Saya memiliki masalah ini dan untuk sedikit saya gunakan

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

untuk mendapatkan data yang dikembalikan dalam suatu objek. tetapi kemudian memiliki masalah lain mendapatkan kesalahan 'hilang) dalam tanda kurung' dan menemukan bahwa jQuery memiliki fungsi khusus untuk mengevaluasi string untuk struktur json:

$.parseJSON(data)

harus melakukan triknya. Ini sebagai tambahan untuk memiliki string json Anda dalam format yang benar tentunya ..


6

Jika Anda menggemakan respons json dan header Anda tidak cocok dengan * / json, Anda dapat menggunakan api jQuery.parseJSON bawaan untuk mengurai respons.

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

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

Bukankah seperti yang kamu pikirkan. Sebagai ekspresi, ini adalah literal Objek, tetapi sebagai pernyataan, ini:

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

Sayangnya eval () tidak memberi Anda cara untuk menentukan apakah Anda memberikan pernyataan atau ekspresi, dan cenderung salah menebak.

Solusi yang biasa memang membungkus apa pun dalam tanda kurung sebelum mengirimkannya ke fungsi eval (). Anda mengatakan Anda sudah mencobanya di server ... jelas entah bagaimana itu tidak berhasil. Ini harus tahan air untuk dikatakan di sisi klien, apa pun yang menerima respons XMLHttpRequest:

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

dari pada:

eval(responseText);

asalkan responnya benar-benar ungkapan, bukan pernyataan. (misalnya, tidak memiliki beberapa klausa yang dipisahkan titik koma atau baris baru.)


Saya pikir jQuery menambahkan tanda kurung secara otomatis saat memproses data permintaan.
strager

2
Jawaban ini sangat membantu saya, karena saya tidak pernah mengerti mengapa orang membungkus JSON dalam tanda kurung.
Andrey Tarantsov


2

Jika Anda menggunakan ASP.NET Web Services menggunakan jQuery, pastikan Anda memiliki yang berikut ini yang disertakan di web.config Anda:

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

2

Saya mengalami masalah serupa dengan ini di mana Firefox 3.5 bekerja dengan baik dan mengurai data JSON saya tetapi Firefox 3.0.6 mengembalikan parseerror. Ternyata itu adalah ruang kosong di awal JSON yang menyebabkan Firefox 3.0.6 melakukan kesalahan. Menghapus ruang kosong memperbaikinya


2

Teknik "eval ()" dan "JSON.parse ()" menggunakan format yang saling eksklusif.

  • Dengan "eval ()" kurung yang diperlukan .
  • Dengan tanda kurung "JSON.parse ()" dilarang .

Hati-hati, ada fungsi "stringify ()" yang menghasilkan format "eval". Untuk ajax, Anda harus menggunakan hanya format JSON.

Meskipun "eval" menggabungkan seluruh bahasa JavaScript, JSON hanya menggunakan sebagian kecil dari bahasa tersebut. Di antara konstruksi dalam bahasa JavaScript yang harus dikenali "eval" adalah "Pernyataan blok" (alias "pernyataan gabungan") ; yang merupakan sepasang atau tanda kurung kurawal "{}" dengan beberapa pernyataan di dalamnya. Tapi kurung kurawal juga digunakan dalam sintaks literal objek. Interpretasi dibedakan oleh konteks di mana kode tersebut muncul. Sesuatu mungkin terlihat seperti objek literal bagi Anda, tetapi "eval" akan melihatnya sebagai pernyataan gabungan.

Dalam bahasa JavaScript, literal objek muncul di sebelah kanan tugas.

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

Literal objek tidak muncul dengan sendirinya.

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

Kembali ke pertanyaan awal OP, yang ditanyakan pada tahun 2008, dia bertanya mengapa hal berikut gagal dalam "eval ()":

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

Jawabannya adalah ini terlihat seperti pernyataan majemuk. Untuk mengubahnya menjadi objek, Anda harus meletakkannya ke dalam konteks di mana pernyataan majemuk tidak mungkin. Itu dilakukan dengan meletakkan tanda kurung di sekitarnya

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

OP juga bertanya mengapa pernyataan serupa lakukan berhasil eval:

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

Jawaban yang sama berlaku - kurung kurawal berada dalam konteks di mana pernyataan majemuk tidak mungkin. Ini adalah konteks larik, " [...]", dan larik bisa berisi objek, tapi tidak bisa berisi pernyataan.

Tidak seperti "eval ()", JSON sangat terbatas kemampuannya. Batasannya disengaja. Perancang JSON menginginkan subset JavaScript yang minimalis, hanya menggunakan sintaks yang dapat muncul di sisi kanan tugas. Jadi jika Anda memiliki beberapa kode yang diurai dengan benar di JSON ...

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

... yang menyiratkan itu juga akan mengurai secara hukum di sisi kanan tugas, seperti ini ..

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

Tapi itu bukan satu-satunya batasan pada JSON. The BNF spesifikasi bahasa untuk JSON sangat sederhana. Misalnya, ini tidak mengizinkan penggunaan tanda kutip tunggal untuk menunjukkan string (seperti JavaScript dan Perl) dan tidak memiliki cara untuk mengekspresikan karakter tunggal sebagai byte (seperti 'C'). Sayangnya, ini juga tidak mengizinkan komentar (yang akan sangat bagus saat membuat file konfigurasi). Keuntungan dari semua batasan tersebut adalah penguraian JSON cepat dan tidak menawarkan kesempatan untuk injeksi kode (ancaman keamanan).

Karena keterbatasan ini, JSON tidak menggunakan tanda kurung. Akibatnya, tanda kurung dalam string JSON merupakan karakter ilegal.

Selalu gunakan format JSON dengan ajax, karena alasan berikut:

  • Pipeline ajax tipikal akan dikonfigurasi untuk JSON.
  • Penggunaan "eval ()" akan dikritik sebagai risiko keamanan.

Sebagai contoh pipeline ajax, pertimbangkan program yang melibatkan server Node dan klien jQuery. Program klien menggunakan panggilan jQuery yang memiliki formulir $.ajax({dataType:'json',...etc.});. JQuery membuat objek jqXHR untuk digunakan nanti, lalu memaketkan dan mengirim permintaan terkait. Server menerima permintaan tersebut, memprosesnya, dan kemudian siap untuk merespons. Program server akan memanggil metode res.json(data)untuk mengemas dan mengirim respons. Kembali ke sisi klien, jQuery menerima respons, berkonsultasi dengan objek jqXHR terkait, dan memproses data yang diformat JSON. Ini semua bekerja tanpa perlu konversi data manual. Responsnya tidak melibatkan panggilan eksplisit ke JSON.stringify () di server Node, dan tidak ada panggilan eksplisit ke JSON.parse () di klien; itu semua ditangani untuk Anda.

Penggunaan "eval" dikaitkan dengan risiko keamanan injeksi kode. Anda mungkin berpikir itu tidak mungkin terjadi, tetapi peretas bisa menjadi sangat kreatif. Selain itu, "eval" bermasalah untuk pengoptimalan Javascript.

Jika Anda menemukan diri Anda menggunakan fungsi "stringify ()", ketahuilah bahwa beberapa fungsi dengan nama itu akan membuat string yang kompatibel dengan "eval" dan tidak dengan JSON. Misalnya, di Node, berikut ini memberi Anda fungsi yang membuat string dalam format yang kompatibel dengan "eval":

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

Ini bisa berguna, tetapi kecuali Anda memiliki kebutuhan khusus, mungkin itu bukan yang Anda inginkan.


1

Jika mengembalikan sebuah array berfungsi dan mengembalikan satu objek tidak, Anda juga dapat mencoba mengembalikan objek tunggal Anda sebagai array yang berisi objek tunggal itu:

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

dengan cara itu Anda mengembalikan struktur data yang konsisten, larik objek, apa pun muatan datanya.

Saya melihat bahwa Anda telah mencoba membungkus objek tunggal Anda dalam "tanda kurung", dan menyarankan ini dengan contoh karena tentu saja JavaScript memperlakukan [..] berbeda dari (..)


1

Jika penangan kesalahan jQuery dipanggil dan objek XHR berisi "kesalahan pengurai", itu mungkin kesalahan pengurai yang muncul kembali dari server.

Apakah skenario hasil ganda Anda saat Anda memanggil layanan tanpa parameter, tetapi rusak saat Anda mencoba menyediakan parameter untuk mengambil rekaman tunggal?

Dari backend apa Anda mengembalikan ini?

Pada layanan ASMX, misalnya, hal itu sering terjadi ketika parameter diberikan ke jQuery sebagai objek JSON, bukan string JSON. Jika Anda memberikan jQuery sebuah objek JSON yang sebenarnya untuk parameter "data" -nya, itu akan membuat serialisasi itu menjadi pasangan k, v standar & dibatasi alih-alih mengirimkannya sebagai JSON.


1

Saya menemukan di beberapa implementasi saya, saya harus menambahkan:

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

yang sepertinya menyelesaikan masalah. Eval atau tidak sepertinya melakukan hal yang sama untuk saya.


Gunakan literal objek saat menginisialisasi objek baru, bukan konstruktor Objek: var obj = {};
Andreas Grech

Ya saya mengerti, var myArray = [] untuk array dan var myObject = {}, terima kasih atas tipnya Dreas
Jay

1

jQuery tersedak kunci JSON tertentu. Saya mengirimkan cuplikan JSON ini dalam PHP:

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

Mengganti nama kunci 'hasil' menjadi sesuatu yang lain berfungsi. Saya kira ini adalah tabrakan kata khusus dari beberapa jenis, dan bisa menjadi bug di jQuery (1.4.2).


1

Dalam lingkungan ColdFusion, satu hal yang akan menyebabkan kesalahan, bahkan dengan JSON yang terbentuk dengan baik, adalah mengaktifkan Enable Request Debugging Output di ColdFusion Administrator (di bawah Debugging & Logging> Debug Output Settings). Informasi debug akan dikembalikan dengan data JSON dan karenanya akan membuatnya tidak valid.


1

coba juga ini

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

dalam kasus saya, server merespons dengan karakter yang tidak diketahui sebelum '{'


1

Saya mendapatkan status = parseerror dan xhr.status = 200.

Masalah bagi saya adalah URL di dalam respons JSON telah '\' beralih ke '/' memperbaiki ini.


0

Saya berjuang dengan ini, dan menghabiskan beberapa jam mencoba mencari tahu, sampai saya menggunakan firebug untuk menunjukkan objek data.

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

-1

menggunakan

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

di sisi server. Di sisi klien gunakan ajax dengan Datatype JSON dan pastikan pengkodean dokumen Anda bukan UTF-8 dengan BOM, itu harus UTF-8.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.