web-dev-qa-db-ja.com

JSON結果で関数を定義することは有効ですか?

WebサイトのJSONレスポンスの一部には、これがありました(...コンテキストのために追加されました):

{..., now:function(){return(new Date).getTime()}, ...}

JSONへの匿名関数の追加は有効ですか? 'time'にアクセスするたびに異なる値が返されることを期待しています。

97
Zachary Scott

番号。

JSONは純粋にデータ記述言語であることを意図しています。 http://www.json.org で述べたように、これは「軽量のデータ交換フォーマット」です。 -プログラミング言語ではありません。

http://en.wikipedia.org/wiki/JSON ごとに、サポートされる「基本タイプ」は次のとおりです。

  • 数値(整数、実数、または浮動小数点)
  • 文字列(バックスラッシュをエスケープした二重引用符付きUnicode)
  • ブール値(trueおよびfalse)
  • 配列(順序付けられた値のシーケンス、コンマ区切りで角括弧で囲まれています)
  • オブジェクト(キーと値のペアのコレクション、コンマ区切りで、中括弧で囲まれています)
  • null
100
Mike

問題は、データ定義言語としてのJSONがJavaScript Object NotationとしてのJSONから進化したことです。 JavascriptはJSONでのevalをサポートしているため、JSONコードをJSON内に(そのユースケースで)入れるのは正当です。 JSONを使用してデータをリモートで渡す場合、JSONにメソッドを配置することはお勧めできません。クライアントとサーバーの相互作用をうまくモデル化していない可能性があるからです。さらに、JSONをデータ記述言語として使用する場合、メソッドを埋め込むことで問題が発生する可能性があります。JSONパーサーの一部はデータ記述のみを念頭に置いて記述されており、構造内のメソッド定義をサポートしていないためです。

Wikipedia JSONエントリー は、JSONにメソッドを含めないための適切なケースになり、セキュリティ上の懸念を引用します。

テキストのソースを完全に信頼し、厳密にJSONに準拠していないテキストを解析して受け入れる必要がある場合を除き、代わりにeval()を避け、JSON.parse()または別のJSON固有のパーサーを使用する必要があります。 JSONパーサーはJSONテキストのみを認識し、悪意のあるJavaScriptを含む可能性がある他のテキストを拒否します。ネイティブJSONサポートを提供するブラウザーでは、JSONパーサーはevalよりもはるかに高速です。ネイティブJSONサポートが次のECMAScript標準に含まれることが期待されています。

16
harschware

私の知る限り、それは標準ではありません。 http://json.org/ を簡単に確認すると、これが確認できます。

7
jldupont

仕様の1つを引用しましょう- http://tools.ietf.org/html/rfc7159#section-12

The JavaScript Object Notation(JSON)Data Interchange Format Specificationの状態:

JSONはJavaScriptのサブセットですが、割り当てと呼び出しを除きます。

JSONの構文はJavaScriptから借用されているため、その言語の「eval()」関数を使用してJSONテキストを解析することができます。一般に、これは容認できないセキュリティリスクを構成します。
データ宣言とともに実行可能コードを含めることができます
。 JSONテキストがそれに準拠する他のプログラミング言語でのeval()のような関数の使用にも同じ考慮事項が適用されます
言語の構文。

そのため、関数がJSON標準の一部ではないことを示すすべての答えは正しいです。

公式の答えは:いいえ、JSONの結果に関数を定義することは無効です!


「コードはデータです」と「データはコードです」ので、答えはイエスかもしれません。 JSONが言語に依存しないデータシリアル化形式として使用されている場合でも、他のタイプを介した「コード」のトンネリングは機能します。

JSON文字列を使用して、JS関数をクライアント側ブラウザーに渡して実行することができます。

[{"data":[["1","2"],["3","4"]],"aFunction":"function(){return \"foo bar\";}"}]

これは、「 文字列として保存されたJavaScriptコードを実行する 」のような質問につながります。

「eval()is evil」フラグを立て、その横に「JSONで関数をトンネリングしない」フラグを付けるように準備してください。

7
Jens A. Koch

いや、間違いなく。

適切なJSONシリアライザーを使用する場合、そのような関数をシリアル化することはできません。有効なOBJECTですが、有効なJSONではありません。そのWebサイトの目的が何であれ、有効なJSONを送信していません。

4
jvenema

JSONはJavaScriptのみのデータ構造ではないため、関数は明示的に除外されます(名前のJSにもかかわらず)。

3
Tatu Ulmanen

短い答えは[〜#〜] no [〜#〜] ...です。

JSONは完全に言語に依存しないテキスト形式ですが、C、C++、C#、Java、JavaScript、Perl、Pythonなど、Cファミリーの言語のプログラマーに馴染みのある規則を使用しています。これらのプロパティにより、JSONは理想的なデータ交換言語になります。

理由を見てください:

ブラウザとサーバー間でデータを交換する場合、データはテキストのみです。

JSONはテキストであり、JavaScriptオブジェクトをJSONに変換し、JSONをサーバーに送信できます。

サーバーから受け取ったJSONをJavaScriptオブジェクトに変換することもできます。

このようにして、複雑な解析や変換を行わずに、データをJavaScriptオブジェクトとして扱うことができます。

しかしwait ...

関数を保存する方法はまだあります。それは広く非推奨ですが、それでも可能です:

stringを保存できると言いました...関数を文字列に変換するのはどうですか?

_const data = {func: '()=>"a FUNC"'};
_

次に、JSON.stringify(data)を使用してデータを文字列化し、_JSON.parse_を使用して解析します(この手順が必要な場合)...

eval文字列関数を実行します(実行する前に、evalの使用はお勧めできません)

_eval(data.func)(); //return "a FUNC"
_
2
Alireza

NodeJS(commonJS構文)を使用することで、このタイプの機能を動作させることができました。当初、外部JSファイル内にJSON構造しかありませんでしたが、その構造は、実行時間。

MyJSONの「Executor」の宣言は必要ありません。

var myJSON = {
    "Hello": "World",
    "Executor": ""
}

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}
0