web-dev-qa-db-ja.com

ノード内の不正なJSON.parse()を安全に処理する

Node/expressの使用-リクエストヘッダーからJSONを取得したいのですが、安全に行いたいです。
何らかの理由で有効なJSONでない場合は問題ありません。falseまたは何でも返すことができ、リクエストを拒否して続行します。問題は、有効なJSONではない場合、構文エラーがスローされることです。通常、構文エラーを爆発させたいが、この場合はそうではない。

var boom = JSON.parse(req.headers.myHeader);

スタックをスクレイプし、その特定のモジュールからの不正な解析呼び出しをチェックしますか?その場合、無視しますか?それは少しおかしいようです。確かにもっと良い方法があります。

編集:try/catchブロックが[〜#〜] a [〜#〜]このエラーを処理する方法であることは承知していますが、ノードアプリで最良の方法ですか?この方法はノードをブロックしますか?

25
tpie

無効なJSON解析エラーをキャッチする最善の方法は、JSON.parse()への呼び出しを_try/catch_ブロックに入れることです。

本当に他のオプションはありません-組み込みの実装は無効なJSONデータに対して例外をスローし、その例外がアプリケーションを停止させないようにする唯一の方法はそれをキャッチすることです。サードパーティのライブラリを使用してもそれは避けられません-JSON.parse()呼び出しで_try/catch_をどこかで実行する必要があります。

唯一の選択肢は、無効なデータ構造をより許容できる独自のJSON解析アルゴリズムを実装することですが、小さな核で1立方メートルの穴を掘るような感じです。

パフォーマンスに関する注意

Node.jsで使用されるv8 JavaScriptエンジン 最適化できません _try/catch_ブロックを含む関数。

更新:v8 4.5以降ではtry/catchを最適化できます 。古いリリースについては、以下を参照してください。

簡単な回避策は、メイン関数を最適化できるように、安全解析ロジックを別の関数に入れることです。

_function safelyParseJSON (json) {
  // This function cannot be optimised, it's best to
  // keep it small!
  var parsed

  try {
    parsed = JSON.parse(json)
  } catch (e) {
    // Oh well, but whatever...
  }

  return parsed // Could be undefined!
}

function doAlotOfStuff () {
  // ... stuff stuff stuff
  var json = safelyParseJSON(data)
  // Tadaa, I just got rid of an optimisation killer!
}
_

JSONの解析が散発的に行われる場合、これはパフォーマンスに顕著な影響を与えない可能性がありますが、使用量が多い機能で不適切に使用すると、応答時間が劇的に増加する可能性があります。

Try/catchのブロックに関する注意

Node.jsのJavaScriptコードのevery.single.statementは、それがどうであれ、一度に1回だけ実行されることに注意してくださいメイン関数、コールバック、または別のモジュールなどから呼び出されます。そのため、すべてのステートメントはプロセスをブロックします。これは必ずしも悪いことではありません-適切に設計されたアプリケーションは、ほとんどの時間を外部リソース(データベース応答、HTTP通信、ファイルシステム操作など)を待つことに費やします。そのため、頻繁に実行されるJavaScriptコードをv8エンジンで最適化して、このブロック状態でできるだけ時間がかからないようにすることが非常に重要です。パフォーマンスに関する注意を参照してください。

53
Robert Rossmann

trycatchを使用できます

function parseMyHeader(){
    try {
      return JSON.parse(req.headers.myHeader);
    } catch(ex){
      return null;
    }
}
8
EJTH

ノード エラー処理のプロダクションプラクティスで説明されているように、標準のtry/catchはnode.jsのJSON.parseエラーを処理する正しい方法です ドキュメントうれしいウェブサイトから:

... try/catchを使用する唯一の一般的なケースは、JSON.parseおよびその他のユーザー入力検証関数です。

これは、アレクサンドルがコメントで提供したnodejitsuへのリンクとも一致しています。

3
tpie

これは、例外時にスクリプトを壊さない方法についてです

Promise.resolve((body)=>{
            let fbResponse = JSON.parse(body);
            // some code for good
        }).catch(error => {
            cl('Parsing error:');
            cl(error);
            // some code for bad
        });
0
user3640561
        var parsed;

        try {
            parsed = JSON.parse(data);
        } catch (e) {
            parsed = JSON.parse(JSON.stringify(data));
        }

        root = parsed;

まあこれは私のために働いた。 Catchでは、JSONに解析する前にデータを文字列に変換しました。

0
Ganesh Todkar