jQuery, JSON'umu AJAX sorgusundan ayrıştırmıyor


88

Sunucumdan döndürülen bazı JSON verilerini jQuery.ajax () kullanarak ayrıştırmakta güçlük çekiyorum

Kullandığım AJAX'ı gerçekleştirmek için:

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

Ve bir dizi öğe döndürürsem, o zaman iyi çalışıyor:

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

Başarı işlevi çağrılır ve doğru nesneyi alır.

Ancak, tek bir nesneyi döndürmeye çalıştığımda:

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

Hata işlevi çağrılır ve xhr 'ayrıştırıcı hatası' içerir. JSON'u kabloyu göndermeden önce sunucuda parantez içine almayı denedim, ancak bu hiçbir fark yaratmıyor. Yine de içeriği Javascript'te bir dizeye yapıştırırsam ve daha sonra eval () işlevini kullanırsam, mükemmel bir şekilde değerlendirir.

Neyi yanlış yaptığıma dair bir fikrin var mı?

Anthony


Yanıtlar:


72

Sunucunuz verileri İçerik Türü olarak mı gönderiyor "*/json"? Değilse, yanıt başlıklarını uygun şekilde değiştirin. "application/json"Örneğin göndermek iyi olur.


İkincisi bu tahmin, bir zamanlar aynı problemi yaşadım ve şaşırtıcı bir şekilde yanlış mime tipini kullandığımı öğrendim. Windows üzerinde localhost üzerinden test yapıyorsanız, bunun farkında olun. Bir yere yüklemeyi ve tekrar test etmeyi deneyin. Localhost üzerinde çalışmasını istiyorsanız, isteği gerçekten uydurmanız gerekir.
Josh

51

Json.org spesifikasyonuna göre, iadeniz geçersizdir. İsimler her zaman alıntılanmıştır, bu yüzden geri dönmelisiniz

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

ve

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

Kurulumunuzla ilgili sorun bu olmayabilir, çünkü bunlardan birinin şu anda çalıştığını söylüyorsunuz, ancak gelecekte başka bir JSON ayrıştırıcısına geçmeniz gerekmesi ihtimaline karşı doğruluk için düzeltilmesi gerekir.


2
Aslında, jQuery 1.4'te (örneğin) { key: 'val' }JSON geçerli değildir.
rfunduk

34

JSON dizeleri çift tırnak içine alınır; tek tırnak geçerli bir ikame değildir.

{"who": "Hello World"}

geçerli ama bu değil ...

{'who': 'Hello World'}

OP meselesi olmasa da, buraya gelenler için kayda değer olduğunu düşündüm.


30

Bu sorun genellikle isteğinizin yanlış mime türü almasından kaynaklanır. Kendi bilgisayarınızda geliştirme yaparken, bazen kendi bilgisayarınız olan "server" dan uygun mime türünü alamıyorsunuz. Tarayıcıda yerel olarak depolanan dosyayı açarak geliştirirken bir kez bu problemle karşılaştım (örneğin url "c: /project/test.html" idi).

Mime türünü geçersiz kılan bir geri arama işlevi eklemek için beforeSend özelliğini kullanmayı deneyin. Bu, sunucu tarafından gönderilen ve arama kodunuz tarafından alınan yanlış mime türüne rağmen kodu json ile başa çıkması için kandırır. Aşağıda bazı örnek kodlar verilmiştir.

Bu soruya göre uygun mime türü application / json'dur , ancak denediğimde application / j-son'un çalıştığını biliyorum (şimdi birkaç yıl önce). Muhtemelen önce application / json'ı denemelisiniz.

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

Sadece önerdiğiniz öneri gönderimin benim için çalıştığını söylemek istiyorum !! ajax çağrım safari ve chrome'da harika çalıştı ama firefox'ta değil. beforeSend'i ekledikten sonra Firefox hemen çıktı. vay!! Teşekkürler!!
Karmen Blake

7

Bu sorunu yaşadım ve bir süre kullandım

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

bir nesnede döndürülen verileri almak için. ancak daha sonra parantez içinde 'eksik' hatası alan başka sorunlar yaşandı ve jQuery'nin özellikle bir json yapısı için bir dizeyi değerlendirmek için bir işlevi olduğunu buldu:

$.parseJSON(data)

hile yapmalı. Bu, json dizenizin elbette uygun biçimde olmasına ek olarak ..


6

Json yanıtını tekrarlıyorsanız ve başlıklarınız * / json ile eşleşmiyorsa, yanıtı ayrıştırmak için yerleşik jQuery.parseJSON api'sini kullanabilirsiniz.

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

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

Düşündüğün gibi değil. Bir ifade olarak, bu bir Object literalidir, ancak bir ifade olarak:

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

Maalesef eval () size bir ifade mi yoksa ifade mi verdiğinizi belirlemenin bir yolunu vermez ve yanlış tahmin etme eğilimindedir.

Olağan çözüm, gerçekten de her şeyi eval () işlevine göndermeden önce parantez içine almaktır. Bunu sunucuda denediğini söylüyorsun ... açıkça bir şekilde bu başarılamıyor. XMLHttpRequest yanıtını alan ne olursa olsun, istemci tarafında söylemek su geçirmez olmalıdır:

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

onun yerine:

eval(responseText);

cevap gerçekten bir ifade olduğu sürece bir ifade değil. (örn. birden çok, noktalı virgül veya satırsonu ile ayrılmış cümle içermiyor.)


JQuery'nin istek verilerini işlerken parantezleri otomatik olarak eklediğini düşünüyorum.
strager

2
İnsanların JSON'u neden parantez içine aldığını hiç anlamadığım için bu cevap bana çok yardımcı oldu.
Andrey Tarantsov


2

ASP.NET Web Hizmetleri'ni jQuery kullanarak kullanıyorsanız, web.config dosyanızda aşağıdakilerin bulunduğundan emin olun:

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

2

Firefox 3.5'in iyi çalıştığı ve JSON verilerimi ayrıştırdığı, ancak Firefox 3.0.6'nın bir ayrıştırıcı hatası verdiği buna benzer bir sorun yaşadım. JSON'un başlangıcında Firefox 3.0.6'nın bir hata atmasına neden olan boş bir alan olduğu ortaya çıktı. Boş alanı kaldırmak onu düzeltti


2

"Eval ()" ve "JSON.parse ()" teknikleri, birbirini dışlayan biçimleri kullanır.

  • "Eval ()" ile parantez gereklidir .
  • "JSON.parse ()" ile parantez yasaktır .

Dikkat edin, "eval" biçimini üreten "stringify ()" işlevleri vardır. Ajax için yalnızca JSON formatını kullanmalısınız.

"Eval" tüm JavaScript dilini içerirken JSON, dilin yalnızca küçük bir alt kümesini kullanır. JavaScript dilindeki "eval" un tanıması gereken yapılar arasında "Blok deyimi" (diğer adıyla "bileşik ifade") bulunur ; bu, içinde bazı ifadeler bulunan bir çift veya kaşlı ayraç "{}". Ancak, nesne değişmezlerinin sözdiziminde küme parantezleri de kullanılır. Yorum, kodun göründüğü bağlama göre farklılık gösterir. Bir şey size gerçek bir nesne gibi görünebilir, ancak "eval" bunu bileşik bir ifade olarak görecektir.

JavaScript dilinde, nesne değişmezleri bir atamanın sağında yer alır.

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

Nesne değişmezleri kendi başlarına oluşmaz.

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

OP'nin 2008'de sorulan orijinal sorusuna geri dönerek, "eval ()" de aşağıdakilerin neden başarısız olduğunu sordu:

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

Cevap, bileşik bir ifade gibi görünmesidir. Bunu bir nesneye dönüştürmek için, onu bileşik bir ifadenin imkansız olduğu bir bağlama koymalısınız. Bu, etrafına parantez koyarak yapılır

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

Benzer bir açıklama neden OP de sorulan yaptım başarıyla eval:

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

Aynı cevap geçerlidir - küme parantezleri bir bileşik ifadenin imkansız olduğu bir bağlamdadır. Bu bir dizi bağlamıdır, "[...] " ve diziler nesneler içerebilir ancak ifade içeremezler.

"Eval ()" 'den farklı olarak, JSON yetenekleri açısından çok sınırlıdır. Sınırlama kasıtlıdır. JSON tasarımcısı, yalnızca bir atamanın sağ tarafında görünebilen sözdizimini kullanarak minimalist bir JavaScript alt kümesi tasarladı. Yani, JSON'da doğru bir şekilde ayrıştıran bir kodunuz varsa ...

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

... bu, bunun gibi bir ödevin sağ tarafında da yasal olarak ayrıştırılacağı anlamına gelir ..

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

Ancak JSON'daki tek kısıtlama bu değil. JSON için BNF dil şartname çok basittir. Örneğin, dizeleri belirtmek için tek tırnakların kullanılmasına izin vermez (JavaScript ve Perl gibi) ve tek bir karakteri bayt olarak ifade etmenin bir yolu yoktur ('C'nin yaptığı gibi). Ne yazık ki, yorumlara da izin vermiyor (bu, yapılandırma dosyalarını oluştururken gerçekten iyi olurdu). Tüm bu sınırlamaların iyi yanı, JSON'un ayrıştırılmasının hızlı olması ve kod yerleştirme (bir güvenlik tehdidi) için hiçbir fırsat sunmamasıdır.

Bu sınırlamalar nedeniyle, JSON'un parantez için kullanımı yoktur. Sonuç olarak, bir JSON dizesindeki bir parantez geçersiz bir karakterdir.

Aşağıdaki nedenlerden dolayı, ajax ile her zaman JSON formatını kullanın:

  • JSON için tipik bir ajax işlem hattı yapılandırılacaktır.
  • "Eval ()" kullanımı bir güvenlik riski olarak eleştirilecektir.

Ajax ardışık düzenine bir örnek olarak, bir Node sunucusu ve bir jQuery istemcisi içeren bir programı düşünün. İstemci programı, forma sahip bir jQuery çağrısı kullanır $.ajax({dataType:'json',...etc.});. JQuery, daha sonra kullanılmak üzere bir jqXHR nesnesi oluşturur, ardından ilişkili isteği paketler ve gönderir. Sunucu isteği kabul eder, işler ve ardından yanıt vermeye hazırdır. Sunucu programı res.json(data), yanıtı paketlemek ve göndermek için yöntemi çağıracaktır . İstemci tarafında, jQuery yanıtı kabul eder, ilişkili jqXHR nesnesine danışır ve JSON formatlı verileri işler. Bunların tümü, manuel veri dönüştürmeye gerek kalmadan çalışır. Yanıt, Node sunucusunda JSON.stringify () öğesine hiçbir açık çağrı ve istemcide JSON.parse () öğesine açık çağrı içermez; hepsi sizin için halledildi.

"Eval" kullanımı, kod yerleştirme güvenlik riskleriyle ilişkilidir. Bunun olmasının bir yolu olmadığını düşünebilirsiniz, ancak bilgisayar korsanları oldukça yaratıcı olabilir. Ayrıca, Javascript optimizasyonu için "eval" sorunludur.

Kendinizi bir "stringify ()" işlevi kullanırken bulursanız, bu ada sahip bazı işlevlerin JSON ile değil "eval" ile uyumlu dizeler oluşturacağını unutmayın. Örneğin, Düğüm'de, aşağıdakiler size "eval" uyumlu biçimde dizeler oluşturan işlev verir:

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

Bu yararlı olabilir, ancak belirli bir ihtiyacınız yoksa, muhtemelen istediğiniz şey bu değildir.


1

Bir dizi döndürmek işe yarıyorsa ve tek bir nesneyi döndürmek işe yaramıyorsa, tek nesnenizi o tek nesneyi içeren bir dizi olarak da döndürmeyi deneyebilirsiniz:

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

bu şekilde, veri yükü ne olursa olsun tutarlı bir veri yapısı, bir dizi nesne döndürürsünüz.

Tek nesnenizi "parantez" içine kaydırmayı denediğinizi görüyorum ve bunu bir örnekle öneriyorsunuz çünkü JavaScript [..], (..)


1

JQuery'nin hata işleyicisi çağrılıyorsa ve XHR nesnesi "ayrıştırıcı hatası" içeriyorsa, bu muhtemelen sunucudan gelen bir ayrıştırıcı hatasıdır.

Servisi bir parametre olmadan çağırdığınızda çoklu sonuç senaryonuz, ancak tek kaydı almak için bir parametre sağlamaya çalıştığınızda kırılıyor mu?

Bunu hangi arka uçtan iade ediyorsunuz?

Örneğin ASMX hizmetlerinde, parametrelerin jQuery'ye JSON dizesi yerine JSON nesnesi olarak sağlandığı durum genellikle budur. JQuery'ye "veri" parametresi için gerçek bir JSON nesnesi sağlarsanız, bunu JSON olarak göndermek yerine standart ve sınırlandırılmış k, v çiftleri halinde serileştirir.


1

Eklemem gereken bazı uygulamalarımda buldum:

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

Bu sorunu çözmüş görünüyordu. Değerlendirin ya da değerlendirmeyin, benim için tamamen aynı şeyi yapıyor gibiydi.


Nesne yapıcısını değil, yeni bir nesneyi başlatırken nesne hazır bilgisini kullanın: var obj = {};
Andreas Grech

Evet, görüyorum, diziler için var myArray = [] ve var myObject = {}, Dreas
Jay

1

jQuery, belirli JSON anahtarlarında tıkanır. Bu JSON snippet'ini PHP'de gönderiyordum:

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

'Sonuç' anahtarını başka bir şeye yeniden adlandırmak işe yarıyor. Bunun bir tür rezerve edilmiş kelime çakışması olduğunu tahmin ediyorum ve jQuery'de (1.4.2) bir hata olabilir.


1

Bir ColdFusion ortamında, iyi biçimlendirilmiş JSON ile bile hataya neden olacak bir şey , ColdFusion Yöneticisinde (Hata Ayıklama ve Günlüğe Kaydetme> Hata Ayıklama Çıktı Ayarları altında) Çıkış İsteği Hata Ayıklama Çıktısının etkinleştirilmesidir. Hata ayıklama bilgileri JSON verileriyle birlikte döndürülecek ve bu nedenle geçersiz kılacaktır.


1

bunu da dene

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

benim durumumda sunucu "{" dan önce bilinmeyen bir karakterle yanıt veriyor


1

Status = parseerror ve xhr.status = 200 alıyordum.

Benim için sorun, JSON yanıtının içindeki URL'lerin '\' olarak değiştirilmesinin bunu düzeltmesiydi.


0

Bununla mücadele ediyordum ve veri nesnesini göstermek için kundakçı kullanana kadar birkaç saat bunu anlamaya çalıştım.

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

-1

kullanım

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

sunucu tarafında. İstemci tarafında Datatype JSON ile ajax kullanın ve belge kodlamanızın BOM ile UTF-8 olmadığından emin olun, UTF-8 olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.