テクニック「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
2008年に尋ねられたOPの元の質問に戻り、彼は「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 の制限はそれだけではありません。JSONのBNF 言語仕様は非常に単純です。たとえば、単一引用符を使用して文字列を示すことはできません (JavaScript や Perl のように)。また、単一の文字をバイトとして表現する方法もありません ('C' のように)。残念ながら、コメントも許可されていません (構成ファイルを作成するときに非常に便利です)。これらすべての制限の利点は、JSON の解析が高速であり、コード インジェクション (セキュリティの脅威) の機会がないことです。
これらの制限により、JSON では括弧は使用されません。したがって、JSON 文字列内の括弧は不正な文字です。
次の理由により、ajax では常に JSON 形式を使用します。
- 典型的な ajax パイプラインは、JSON 用に構成されます。
- 「eval()」の使用は、セキュリティ リスクとして批判されます。
ajax パイプラインの例として、ノード サーバーと 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
これは便利かもしれませんが、特別な必要がない限り、おそらくあなたが望むものではありません。