「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に対する制限はそれだけではありません。JSONのBNF言語仕様は非常に単純です。たとえば、(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
これは便利ですが、特定のニーズがない限り、おそらく望んでいるものではありません。