安全地处理节点中的错误JSON.parse()

tpi*_*pie 27 javascript json node.js express

使用node/express - 我想从请求头中获取一些JSON,但我想安全地完成它.
如果由于某种原因它不是有效的JSON,它没关系,它只能返回false或者其他什么,它只会拒绝请求并继续前进.问题是,如果它不是有效的JSON,它会抛出语法错误.通常我希望语法错误爆炸,但在这种情况下不是.

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

我是否刮掉堆栈并检查来自该特定模块的错误解析调用,如果是这样,它会忽略它?这看起来有点疯狂.当然有更好的方法.

编辑:我知道try/catch块是一种处理此错误的方法,但它是节点应用程序中的最佳方式吗?这样会阻塞节点吗?

Rob*_*ann 56

赶上无效JSON解析错误,最好的办法是把调用JSON.parse()try/catch块.

你真的没有任何其他选择 - 内置实现会对无效的JSON数据抛出异常,防止该异常暂停应用程序的唯一方法就是捕获它.即使使用第三方库也无法避免 - 他们必须try/catchJSON.parse()某个地方打电话.

唯一的选择是实现自己的JSON解析算法,这种算法可能对无效数据结构更加宽容,但这就像用一个小核心挖一个1立方米的洞一样.

关于性能的说明

Node.js使用的v8 JavaScript引擎无法优化包含try/catch块的函数.

更新: v8 4.5及以上版本可以优化try/catch.对于旧版本,请参阅下文.

一个简单的解决方法是将安全解析逻辑放入一个单独的函数中,以便仍然可以优化main函数:

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!
}
Run Code Online (Sandbox Code Playgroud)

如果偶尔进行JSON解析,这可能不会对性能产生明显影响,但如果在使用量较大的函数中使用不当,可能会导致响应时间显着增加.

关于try/catch被阻止的注意事项

应该注意的是,Node.js 中的每个.single.statement只能一次执行一次,无论是从主函数调用还是从回调调用,或者从不同的模块调用.因此,每个语句都会阻止该过程.这不一定是坏事 - 设计良好的应用程序将花费大部分时间等待外部资源(数据库响应,HTTP通信,文件系统操作等).因此,非常重要的是,v8引擎可以优化频繁执行的JavaScript代码,因此在此阻塞状态下花费尽可能少的时间 - 请参阅有关性能的说明.


EJT*_*JTH 8

你可以使用trycatch

function parseMyHeader(){
    try {
      return JSON.parse(req.headers.myHeader);
    } catch(ex){
      return null;
    }
}
Run Code Online (Sandbox Code Playgroud)