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


98

WebサイトのJSON応答の一部にこれがありました(...コンテキストに追加):

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

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


JSONはブラウザーで正常に解析されましたか?もしそうなら、はいそれは(その点で)有効です。
ハーシュウェア

7
@harschware-JSONがJavaScriptに関連している場合にのみ当てはまります。言語に依存しないデータのシリアル化形式としては、これは誤りであり、問​​題を解決するための道です。
jsoverson

@jsoverson-同意する。以下の私の答えを参照してください。
ハーシュウェア2010年

1
この質問に自分で答えるのは簡単です。Webキットインスペクタを開いて実行しますJSON.parse('{now:function(){return(new Date).getTime()}')。インスペクターは言う:JSON仕様をUncaught SyntaxError: Unexpected token n一目見るとこれが確認されます。「値」セクションに焦点を当てます。
Mark E. Haase 2015年

回答:


103

番号。

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

パーhttp://en.wikipedia.org/wiki/JSON、サポート「の基本的なタイプは、」以下のとおりです。

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

2
@Dr。Zim、いいえ、nullと比較するa==null?1:a.toString()==""と、これは何ですか?これは、a = nullの場合、1 / trueを返します。 ""の場合、空の文字列を意味し、1 / trueを取得します。 nullでも ""でもない場合は0 / falseを返します。これを複製して[]と連携させることができ、{}を単に?1:a==[]?1:a.toString()=={}.toString();前のスニペットに追加するだけです。多分この関数はあなたを助けるでしょう。代わりに(true / false)isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})を使用します?1:0?true:false
JamesM-SiteGen

10
同時に、関数もデータです。
アーガイル

2
JSONを使用して「さらにデータ」をフェッチする方法を見つけているときに、私はここに着陸しました。クライアントが次に呼び出すRESTなどのAPIについて心配することなく、クライアントに(サーバーから)追加のデータを取得する方法を通知すると便利です。
Ravindranath Akila 2014年

3
@RavindranathAkila RESTは、可能な次のAPI呼び出しが呼び出しで公開されることを意味します。つまり、実行したRESTリクエストは、(アプリケーションの決定ロジックとデータに基づいて)実行したい将来のリクエストを通知します。これの完全な例は、データ要素が返されるGithub APIですが、それらの一部は他のAPIリクエストリソースにつながります。
Jens A. Koch

1
@Jens-AndréKochありがとう!チェックアウトします
Ravindranath Akila

16

問題は、データ定義言語としての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標準に含まれる予定です。


2
JSONという言葉を口語的に使用している可能性がありますが、正式には「JSON」はECMA標準であり、エンコードされる関数オブジェクトを公開していません。「JSON」と言ったときに、どの機能を参照しているかが曖昧であってはなりません。それが標準を持つことの要点です。
Mark E. Haase 2015年

今日もそうだと思います。したがって、私は「進化」用語を使用...私は引用するソースを持っていないが、私はJSONはECMAは、Javascriptのゲームに入って来た前の造語だったと信じて、そしてJSON前に、標準のデータ交換形式だった
harschware

@harschware RFC 4627によると、JSONはECMAから作成されました。
ジェナスローン

9

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

ザ・JavaScriptのオブジェクト表記法(JSON)データ交換フォーマット仕様の状態:

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を介して関数をトンネリングしない」フラグをその横に貼り付ける準備をしてください。



4

いいえ、違います。

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


2
私はJSON-Libを使用していて、それは素晴らしいシリアライザであると考えています。[使用方法のページ](json-lib.sourceforge.net/usage.html)から、関数が正常にシリアル化されることがわかります
harschware

興味深い...これまでに見たことがない。仕様は明確ではありませんが(json.orgは、JSONは言語に依存しないことを明示的に述べており、その関数定義はそうではありません)、それにもかかわらず興味深いものです。
jvenema

それは言語に依存しないことになっているのはおかしいですが、JSONはJavaScript Object Notationを意味しますhmm weird ..
Nate-Wilkins '18

3

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


3

短い答えはNOです...

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

理由を見てください:

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

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

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

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

でも待って ...

関数を保存する方法はまだありますが、お勧めできませんが、それでも可能です。

保存できますstring...関数を文字列に変換してみませんか?

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

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

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

eval(data.func)(); //return "a FUNC"

0

NodeJS(commonJS構文)を使用して、このタイプの機能を機能させることができました。元々は、いくつかの外部JSファイル内にJSON構造しかありませんでしたが、その構造をよりクラスにしたいと思いました。実行時。

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

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

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

-3

JSONの関数式は完全に可能です。二重引用符で囲むことを忘れないでください。以下は、noSQLデータベース設計の例です。

{
  "_id": "_design/testdb",
  "views": {
    "byName": {
      "map": "function(doc){if(doc.name){emit(doc.name,doc.code)}}"
    }
  }
}


問題は文字列ではなく関数についてです。JSONは文字列値をサポートしますが、関数はサポートしません。詳細についてはマイクの回答を参照してください
jannis

@jannisでも可能です。のような自己呼び出し機能を追加した場合。ここの人々はどうやらその答えを知らないらしい。
Roj

-4

evalは推奨されませんが、これは機能します。

<!DOCTYPE html>
<html>
<body>

<h2>Convert a string written in JSON format, into a JavaScript function.</h2>

<p id="demo"></p>

<script>
    function test(val){return val + " it's OK;}
    var someVar = "yup";
    var myObj = { "func": "test(someVar);" };
    document.getElementById("demo").innerHTML = eval(myObj.func);
</script>

</body>
</html>

1
この例でHTMLを使用する必要がないため、投票は棄却されました。これは5年前のコーディングスタイルで、引用符が欠落しています。JSONファイルには、シリアル化または格納できない関数が含まれているとは限りません。 SQL DBなし
Martijn Scheffer

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