JQuery.ajax()を使用してサーバーから返されたJSONデータの解析に問題があります
私が使用しているAJAXを実行するには:
$.ajax({
url: myUrl,
cache: false,
dataType: "json",
success: function(data){
...
},
error: function(e, xhr){
...
}
});
そして、項目の配列を返す場合、それはうまく機能します:
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
Success関数が呼び出され、正しいオブジェクトを受け取ります。
ただし、単一のオブジェクトを返そうとすると:
{ title: "One", key: "1" }
エラー関数が呼び出され、xhrには「parsererror」が含まれます。ワイヤーを介して送信する前に、サーバー上のかっこでJSONをラップしようとしましたが、違いはありません。それでも、コンテンツをJavascriptの文字列に貼り付けてからeval()関数を使用すると、完全に評価されます。
私が間違っていることは何ですか?
アンソニー
サーバーはデータをContent-Type "*/json"
として送信していますか?そうでない場合は、それに応じて応答ヘッダーを変更します。たとえば、"application/json"
を送信しても問題ありません。
json.org 仕様によると、返品は無効です。名前は常に引用されるため、返される必要があります
{ "title": "One", "key": "1" }
そして
[ { "title": "One", "key": "1" }, { "title": "Two", "key": "2" } ]
これはセットアップの問題ではないかもしれません。そのうちの1つは現在動作していると言いますが、将来別のJSONパーサーに切り替える必要がある場合に備えて修正する必要があります。
JSON文字列はdouble引用符でラップされます。単一引用符は有効な代替ではありません。
{"who": "Hello World"}
有効ですが、これは無効です...
{'who': 'Hello World'}
OPの問題ではありませんが、ここに着陸する他の人にとっては注目に値すると考えました。
この問題は通常、リクエストが間違ったMIMEタイプを受け取ったために発生します。自分のコンピューターで開発する場合、自分のコンピューターである「サーバー」から適切なMIMEタイプを受け取れないことがあります。ブラウザでローカルに保存されたファイルを開いて開発するときに、この問題に一度遭遇しました(たとえば、URLは「c:/project/test.html」でした)。
BeforeSendプロパティを使用して、MIMEタイプをオーバーライドするコールバック関数を追加してみてください。これにより、誤ったMIMEタイプがサーバーによって送信され、呼び出しコードによって受信されるにもかかわらず、コードをだましてjsonを処理します。以下にコード例を示します。
この質問 によると、適切なMIMEタイプはapplication/jsonですが、application/j-sonを試してみたとき(現在は数年前)に機能したことがわかります。おそらく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...
}
});
私はこの問題を抱えていて、少しの間使用しました
eval('('+data+')')
オブジェクトで返されるデータを取得します。しかしその後、「括弧内に)が見つからない」というエラーを取得する他の問題が発生し、jQueryにはjson構造の文字列を評価するための関数があることがわかりました。
$.parseJSON(data)
トリックを行う必要があります。これはもちろん、適切な形式のJSON文字列を持つことに加えてです。
Json応答をエコーアウトしていて、ヘッダーが*/jsonと一致しない場合、組み込みのjQuery.parseJSON APIを使用して応答を解析できます。
response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );
{ title: "One", key: "1" }
あなたが思うものではありません。式としては、オブジェクトリテラルですが、ステートメントとしては、次のとおりです。
{ // 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
残念ながら、eval()は、ステートメントまたは式のどちらを指定するかを指定する方法を提供しておらず、間違った推測をする傾向があります。
通常の解決策は、実際にeval()関数に送信する前にanythingを括弧で囲むことです。あなたはサーバー上でそれを試みたと言います...明らかにどういうわけかそれは通過していません。 XMLHttpRequest応答を受信しているものは何でも、クライアント側で言うのは防水である必要があります。
eval('('+responseText+')');
の代わりに:
eval(responseText);
応答が実際にはステートメントではなく式である限り。 (たとえば、セミコロンまたは改行で区切られた複数の句はありません。)
次のように、PHPでヘッダーコンテンツタイプを設定する必要があります。
<?php
header('Content-type:application/json');
?>
理解を深めるためにこれらのビデオをご覧ください。
これに似た問題があり、Firefox 3.5は正常に動作し、JSONデータを解析しましたが、Firefox 3.0.6はparseerrorを返しました。 Firefox 3.0.6がエラーをスローする原因となったのは、JSONの開始時の空白スペースでした。空白を削除すると修正されました
「eval()」および「JSON.parse()」の手法は、相互に排他的な形式を使用します。
「eval」形式を生成する「stringify()」関数があることに注意してください。 ajaxの場合、JSON形式のみを使用する必要があります。
「eval」にはJavaScript言語全体が組み込まれていますが、JSONは言語のごく一部しか使用していません。 「eval」が認識しなければならないJavaScript言語の構成要素には、 "Block statement"(別名「compound statement ") ;があります。ペアまたは中括弧 "{}"であり、内部にいくつかのステートメントがあります。しかし、中かっこはオブジェクトリテラルの構文でも使用されます。解釈は、コードが表示されるコンテキストによって区別されます。何かはオブジェクトリテラルのように見えるかもしれませんが、「eval」はそれを複合ステートメントとして認識します。
JavaScript言語では、オブジェクトリテラルは割り当ての右側にあります。
var myObj = { ...some..code..here... };
オブジェクトリテラルは、単独では発生しません。
{ ...some..code..here... } // this looks like a compound statement
2008年に尋ねられたOPの元の質問に戻って、「eval()」で次が失敗する理由を尋ねました。
{ title: "One", key: "1" }
答えは、複合ステートメントのように見えることです。オブジェクトに変換するには、複合ステートメントが不可能なコンテキストに配置する必要があります。それは、括弧を囲むことによって行われます
( { title: "One", key: "1" } ) // not a compound statment, so must be object literal
OPは、同様のステートメントdidが正常に評価される理由も尋ねました。
[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]
同じ答えが当てはまります。中括弧は、複合ステートメントが不可能な状況にあります。これは配列コンテキスト「[...]
」であり、配列にはオブジェクトを含めることができますが、ステートメントを含めることはできません。
「eval()」とは異なり、JSONの機能は非常に制限されています。制限は意図的です。 JSONの設計者は、割り当ての右側に表示される構文のみを使用して、JavaScriptの最小限のサブセットを意図していました。 JSONを正しく解析するコードがある場合...
var myVar = JSON.parse("...some...code...here...");
...これは、このように、割り当ての右側でも法的に解析することを意味します。
var myVar = ...some..code..here... ;
ただし、JSONの制限はそれだけではありません。 JSONのBNF言語仕様 は非常に単純です。たとえば、単一引用符を使用して文字列を示すことはできず(JavaScriptやPerlのように)、単一の文字をバイトとして表現する方法はありません( 'C'のように)。残念ながら、コメントも許可していません(設定ファイルを作成するときは本当に素晴らしいでしょう)。これらすべての制限の利点は、JSONの解析が高速であり、コードインジェクションの機会がないことです(セキュリティ上の脅威)。
これらの制限のため、JSONは括弧を使用しません。そのため、JSON文字列の括弧は無効な文字です。
次の理由により、Ajaxで常にJSON形式を使用します。
Ajaxパイプラインの例として、NodeサーバーとjQueryクライアントを含むプログラムを考えてください。クライアントプログラムは、$.ajax({dataType:'json',...etc.});
という形式のjQuery呼び出しを使用します。 JQueryは、後で使用するためにjqXHRオブジェクトを作成し、関連するリクエストをパッケージ化して送信します。サーバーは要求を受け入れて処理し、応答する準備が整います。サーバープログラムはメソッドres.json(data)
を呼び出してパッケージ化し、応答を送信します。クライアント側に戻ると、jQueryは応答を受け入れ、関連するjqXHRオブジェクトを調べ、JSON形式のデータを処理します。これはすべて、手動のデータ変換を必要とせずに機能します。応答には、NodeサーバーでのJSON.stringify()の明示的な呼び出しや、クライアントでのJSON.parse()の明示的な呼び出しは含まれません。それはすべてあなたのために処理されます。
「評価」の使用は、コードインジェクションのセキュリティリスクに関連付けられています。起こりうる方法はないと思うかもしれませんが、ハッカーは非常に創造的になります。また、「eval」はJavascriptの最適化に問題があります。
「stringify()」関数の使用を使用していることに気付いた場合、その名前の一部の関数はJSONではなく「eval」と互換性のある文字列を作成することに注意してください。たとえば、Nodeでは、「eval」互換形式で文字列を作成する関数が次のように提供されます。
var stringify = require('node-stringify'); // generates eval() format
これは便利な場合もありますが、特定のニーズがない限り、おそらく望んでいないものです。
JQueryを使用してASP.NET Webサービスを使用している場合は、web.configに次のものが含まれていることを確認してください。
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
ColdFusion環境では、整形式のJSONであってもエラーを引き起こす1つのことは、ColdFusion AdministratorでEnable Debugging Outputがオンになっていることです(Debugging&Logging> Debug Output Settingsの下)。デバッグ情報はJSONデータとともに返されるため、無効になります。
Status = parseerrorおよびxhr.status = 200を取得していました。
私にとっての問題は、JSON応答内のURLが '\'から '/'に切り替わってこれを修正したことです。
これも試してください
$.ajax({
url: url,
data:datas,
success:function(datas, textStatus, jqXHR){
var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('{')));
})};
私の場合、サーバーは「{」の前に不明な文字で応答します
配列を返すことが機能し、単一のオブジェクトを返さない場合、単一のオブジェクトを含む配列として単一のオブジェクトを返すこともできます。
[ { title: "One", key: "1" } ]
そうすれば、データペイロードに関係なく、一貫したデータ構造、オブジェクトの配列を返します。
単一のオブジェクトを「かっこ」でラップしようとしていることがわかります。もちろん、JavaScriptが[..]と(..)
JQueryのエラーハンドラが呼び出され、XHRオブジェクトに「パーサーエラー」が含まれている場合、それはおそらくサーバーから戻ってきたパーサーエラーです。
パラメーターを指定せずにサービスを呼び出した場合、複数の結果のシナリオになりますが、単一のレコードを取得するためのパラメーターを指定しようとすると破損しますか?
これをどのバックエンドから返しますか?
たとえば、ASMXサービスでは、パラメータがJSON文字列ではなくJSONオブジェクトとしてjQueryに提供される場合がよくあります。 jQueryの「データ」パラメーターに実際のJSONオブジェクトを指定すると、JSONとして送信する代わりに、標準の区切りのk、vペアにシリアル化されます。
jQueryは特定のJSONキーでチョークします。私はPHPでこのJSONスニペットを送信していました。
echo json_encode((object) array('result' => 'success'));
「結果」キーの名前を他の何かに変更します。これは何らかの予約語の競合であり、jQuery(1.4.2)のバグである可能性があります。
私が追加しなければならなかった実装のいくつかを見つけました:
obj = new Object; obj = (data.obj);
これで問題が解決したようです。評価してもしなくても、まったく同じように思えた。
私はこれに苦労していたので、firebugを使用してデータオブジェクトを表示するまで、数時間かけてこれを把握しようとしました。
var data = eval("(" + data.responseText + ")");
console.log(data.count);