jQueryがAJAXクエリからのJSONを解析しない


88

サーバーから返されたJSONデータをjQuery.ajax()を使用して解析するのが難しい

私が使用しているAJAXを実行するには:

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

そして、私がアイテムの配列を返す場合、それはうまくいきます:

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

成功関数が呼び出され、正しいオブジェクトを受け取ります。

ただし、単一のオブジェクトを返そうとしている場合:

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

エラー関数が呼び出され、xhrに「parsererror」が含まれています。JSONを回線で送信する前にサーバーで括弧で囲んでみましたが、違いはありません。それでも、コンテンツをJavaScriptの文字列に貼り付けてからeval()関数を使用すると、完全に評価されます。

私が間違っていることはありますか?

アンソニー


回答:


72

サーバーはContent-Typeとしてデータを送信しています"*/json"か?そうでない場合は、それに応じて応答ヘッダーを変更します。"application/json"たとえば、送信で問題ありません。


第二に、この推測では、同じ問題が一度発生し、驚くべきことに、間違ったMIMEタイプを使用していることがわかりました。Windowsでlocalhostを使用してテストしている場合は、これに十分注意してください。どこかにアップロードして、もう一度テストしてみてください。localhostで動作させる場合は、リクエストを実際に処理する必要があります。
Josh、

51

json.org仕様によると、戻り値は無効です。名前は常に引用符で囲まれているため、戻る必要があります

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

そして

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

これらの1つが今は機能すると言うので、これは設定の問題ではないかもしれませんが、将来的に別のJSONパーサーに切り替える必要がある場合に備えて、正確性のために修正する必要があります。


2
実際、jQuery 1.4では(たとえば){ key: 'val' }は有効なJSONではありません。
rfunduk

34

JSON文字列は二重引用符で囲まれます。単一引用符は有効な代用ではありません。

{"who": "Hello World"}

有効ですが、これは無効です...

{'who': 'Hello World'}

OPの問題ではありませんが、ここに上陸した他の人には注目に値するものだと思いました。


30

この問題は通常、リクエストが誤った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...
 }
});

あなたが提案するbeforeSend提案が私のために働いたことを言いたいだけです!! 私のajax呼び出しは、サファリとクロームではうまくいきましたが、Firefoxではうまくいきませんでした。beforeSendを追加するとすぐに、Firefoxが正常に機能し始めました。ワオ!!ありがとう!!
Karmen Blake、

7

私はこの問題があり、少しの間使用しました

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

オブジェクトで返されたデータを取得します。しかしその後、「括弧内の欠落」エラーが発生する他の問題が発生し、jQueryにはjson構造の文字列を評価するための関数が含まれていることがわかりました。

$.parseJSON(data)

トリックを行う必要があります。これはもちろん、json文字列を適切な形式にすることに加えます。


6

json応答をエコー出力していて、ヘッダーが*​​ / jsonと一致しない場合は、組み込みのjQuery.parseJSON APIを使用して応答を解析できます。

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

4
{ 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()関数に送信する前に、何かを括弧で囲むことです。あなたはサーバーでそれを試したと言います...明らかに何とかそれは通り抜けていません。XMLHttpRequest応答を受信するものは何でも、クライアント側で言うことは防水でなければなりません。

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

の代わりに:

eval(responseText);

応答が実際にはステートメントではなく式である限り。(たとえば、セミコロンまたは改行で区切られた複数の句はありません。)


jQueryは、要求データを処理するときに括弧を自動的に追加すると思います。
ストレッジャー、2008年

2
なぜJSONが括弧で囲まれているのか理解できなかったので、この答えはとても役に立ちました。
Andrey Tarantsov、2010年

3

次のように、phpでヘッダーコンテンツタイプを設定する必要があります。

 <?php

 header('Content-type:application/json');

 ?>

よりよく理解するためにこれらのビデオを見てください...

リファレンス:http : //www.youtube.com/watch?v=EvFXWqEqh6o


2

jQueryを使用してASP.NET Webサービスを使用している場合は、web.configに以下が含まれていることを確認してください。

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

2

これと同様の問題がありましたが、Firefox 3.5は正常に機能し、JSONデータを解析しましたが、Firefox 3.0.6は解析エラーを返しました。Firefox 3.0.6がエラーをスローする原因となったのは、JSONの最初の空白スペースであることがわかりました。空白を取り除いて修正


2

「eval()」と「JSON.parse()」の手法は、相互に排他的なフォーマットを使用します。

  • 「eval()」では括弧が必要です
  • "JSON.parse()"では、括弧は禁止されています。

「eval」フォーマットを生成する「stringify()」関数があることに注意してください。ajaxの場合は、JSON形式のみを使用する必要があります。

「eval」にはJavaScript言語全体が組み込まれていますが、JSONはその言語のごく一部のみを使用しています。「eval」が認識しなければならないJavaScript言語の構成には、「ブロックステートメント」(別名「複合ステートメント」)があります。これは、ペアまたは中括弧 "{}"であり、中にいくつかのステートメントがあります。ただし、波括弧はオブジェクトリテラルの構文でも使用されます。解釈は、コードが現れるコンテキストによって区別されます。何かはオブジェクトリテラルのように見えるかもしれませんが、「eval」はそれを複合ステートメントと見なします。

JavaScript言語では、オブジェクトリテラルは割り当ての右側にあります。

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

オブジェクトリテラルは、それ自体では発生しません。

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

OPの元の質問に戻り、2008年に尋ねたところ、彼は次の理由で「eval()」が失敗する理由を尋ねました。

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

答えは、それは複合ステートメントのように見えるということです。これをオブジェクトに変換するには、複合ステートメントが不可能なコンテキストに配置する必要があります。括弧で囲みます

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

OPは、同様のステートメント正常に評価された理由も尋ねました。

[ { 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に対する制限はそれだけではありません。JSONBNF言語仕様は非常に単純です。たとえば、(JavaScriptやPerlのように)文字列を示すために単一引用符を使用することはできません。また、( 'C'のように)単一の文字をバイトとして表す方法はありません。残念ながら、これもコメントを許可しません(構成ファイルを作成するときに本当に便利です)。これらすべての制限の利点は、JSONの解析が高速であり、コードインジェクション(セキュリティ上の脅威)の機会がないことです。

これらの制限のため、JSONは括弧を使用しません。したがって、JSON文字列の括弧は不正な文字です。

次の理由により、常にajaxでJSON形式を使用します。

  • 典型的なajaxパイプラインはJSON用に構成されます。
  • 「eval()」の使用は、セキュリティリスクとして批判されます。

ajaxパイプラインの例として、NodeサーバーとjQueryクライアントを含むプログラムを考えます。クライアントプログラムは、という形式のjQuery呼び出しを使用します$.ajax({dataType:'json',...etc.});。jQueryは、後で使用できるようにjqXHRオブジェクトを作成し、関連するリクエストをパッケージ化して送信します。サーバーは要求を受け入れて処理し、応答する準備が整います。サーバープログラムは、メソッドres.json(data)を呼び出して応答をパッケージ化して送信します。クライアント側に戻ると、jQueryは応答を受け入れ、関連するjqXHRオブジェクトを調べ、JSON形式のデータを処理します。これはすべて、手動のデータ変換を必要とせずに機能します。応答には、NodeサーバーでのJSON.stringify()への明示的な呼び出しや、クライアントでのJSON.parse()への明示的な呼び出しは含まれません。それはすべてあなたのために処理されます。

「eval」の使用は、コードインジェクションのセキュリティリスクに関連しています。起こり得る方法はないと思うかもしれませんが、ハッカーはかなり創造的になることができます。また、「eval」はJavascriptの最適化に問題があります。

「stringify()」関数を使用している場合は、その名前の一部の関数がJSONではなく「eval」と互換性のある文字列を作成することに注意してください。たとえば、Nodeでは、次のようにして、「eval」互換の形式で文字列を作成する関数を提供します。

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

これは便利ですが、特定のニーズがない限り、おそらく望んでいるものではありません。


1

配列を返すことが機能し、単一のオブジェクトを返すことが機能しない場合は、単一のオブジェクトを、その単一のオブジェクトを含む配列として返すこともできます。

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

これにより、データペイロードに関係なく、一貫したデータ構造、オブジェクトの配列を返すことができます。

私はあなたが単一のオブジェクトを「かっこ」でラップしようとしたことを確認しました、そしてもちろんJavaScriptが[..]を(..)とは異なる方法で扱うので、これを例とともに提案します


1

jQueryのエラーハンドラーが呼び出されていて、XHRオブジェクトに「パーサーエラー」が含まれている場合、それはおそらくサーバーから返されるパーサーエラーです。

パラメーターなしでサービスを呼び出した場合の複数結果シナリオはありますが、単一のレコードを取得するためにパラメーターを指定しようとするとうまくいきませんか?

これをどのバックエンドから戻していますか?

たとえば、ASMXサービスでは、パラメーターがJSON文字列ではなくJSONオブジェクトとしてjQueryに提供される場合がよくあります。「データ」パラメーターの実際のJSONオブジェクトをjQueryに提供すると、JSONとして送信する代わりに、それを標準&区切りのk、vペアにシリアライズします。


1

追加しなければならない実装の一部を見つけました。

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

問題を解決したようです。Evalかどうかは、まったく同じでした。


新しいオブジェクトを初期化するときは、オブジェクトコンストラクターではなくオブジェクトリテラルを使用します。var obj = {};
Andreas Grech

ええ、そうです、var myArray = []配列とvar myObject = {}、ヒントのおかげですDreas
Jay

1

jQueryは、特定のJSONキーをチョークします。私はこのJSONスニペットをPHPで送信していました:

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

「結果」キーの名前を別の名前に変更すると機能します。これはある種の予約語の衝突であり、jQuery(1.4.2)のバグである可能性があります。


1

ColdFusion環境でエラーが発生する原因の1つは、整形式のJSONでも、ColdFusion Administratorで(デバッグとロギング>デバッグ出力の設定)の[ リクエストのデバッグ出力有効にする]をオンにすることです。デバッグ情報はJSONデータとともに返されるため、無効になります。


1

これも試して

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

私の場合、サーバーは「{」の前に不明な文字で応答します


1

status = parseerrorおよびxhr.status = 200を取得していました。

私にとっての問題は、JSON応答内のURLの '\'が '/'に切り替わっていることで、これが修正されました。


0

私はこれに苦労していて、firebugを使用してデータオブジェクトを表示するまで、数時間かけてこれを理解しようとしました。

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

-1

使用する

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

サーバー側。クライアント側では、データタイプJSONでajaxを使用し、ドキュメントのエンコードがBOMのUTF-8ではなく、UTF-8である必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.