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

时间:2015-04-22 12:42:24

标签: javascript json node.js express

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

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

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

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

5 个答案:

答案 0 :(得分:49)

捕获无效JSON解析错误的最佳方法是将对JSON.parse()的调用置于try/catch块。

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

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

关于性能的说明

包含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! } 块的Node.js cannot optimise函数使用的v8 JavaScript引擎。

更新: v8 4.5 and above can optimise try/catch。对于旧版本,请参阅下文。

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

select * from contacts where title ilike '%cto%';

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

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

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

答案 1 :(得分:8)

您可以使用trycatch

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

答案 2 :(得分:3)

标准的try / catch是处理node.js中JSON.parse错误的正确方法,如joyent网站的节点production practices for error handling文档中所述,该文档说:

  

...你使用try / catch的唯一常用情况是JSON.parse   和其他用户输入验证功能。

这也与Aleksandr在评论中提供的nodejitsu链接一致。

答案 3 :(得分:0)

        var parsed;

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

        root = parsed;

这对我有用。 在Catch中,我将数据转换为stringify,然后再将其解析为JSON。

答案 4 :(得分:0)

这是关于如何在异常

期间不破坏脚本
Promise.resolve((body)=>{
            let fbResponse = JSON.parse(body);
            // some code for good
        }).catch(error => {
            cl('Parsing error:');
            cl(error);
            // some code for bad
        });