安全地处理节点中的错误 JSON.parse()
Posted
技术标签:
【中文标题】安全地处理节点中的错误 JSON.parse()【英文标题】:Handling bad JSON.parse() in node safely 【发布时间】:2015-06-30 03:12:12 【问题描述】:使用节点/快递 - 我想从请求标头中获取一些 JSON,但我想安全地做到这一点。 如果由于某种原因它不是有效的 JSON,那很好,它可以返回 false 或其他什么,它只会拒绝请求并继续。问题是如果它不是有效的 JSON,它会引发语法错误。通常我希望出现语法错误,但在这种情况下不会。
var boom = JSON.parse(req.headers.myHeader);
我是否从该特定模块刮取堆栈并检查是否存在错误的解析调用,如果是这种情况,它会忽略它吗?这似乎有点疯狂。肯定有更好的方法。
编辑: 我知道 try/catch 块是处理此错误的 A 方式,但它是节点应用程序中的最佳方式吗?这种方式会阻塞节点吗?
【问题讨论】:
proper way to catch exception from javascript method JSON.parse 的可能重复项 我的编辑是否清除或确认它是重复的? try catch 块是同步的,并且有可能锁定节点......这似乎不是问题,但我不确定。 docs.nodejitsu.com/articles/errors/what-is-try-catch - 阅读最后一段。还有joyent.com/developers/node/design/errors. 我认为这里的问题是它不会引发正确的错误。因此为什么你会看到这样的例子:_.attempt(JSON.parse.bind(null, str)); 【参考方案1】:您可以使用try
和catch
function parseMyHeader()
try
return JSON.parse(req.headers.myHeader);
catch(ex)
return null;
【讨论】:
您也可以返回null
(计算结果为假),以便解析
你完全正确。当然你应该返回 null!
因为 JSON.parse() 永远不会返回 undefined,也许在解析错误时返回 undefined 可能有助于识别解析错误【参考方案2】:
标准的 try/catch 是在 node.js 中处理 JSON.parse 错误的正确方法,正如 Joyent 网站的节点 production practices for error handling 文档中所提到的那样:
...使用 try/catch 的唯一常用情况是 JSON.parse 和其他用户输入验证功能。
这也与 Aleksandr 在评论中提供的 nodejitsu 链接一致。
【讨论】:
【参考方案3】:捕获无效 JSON 解析错误的最佳方法是将对 JSON.parse()
的调用放到 try/catch
块中。
您确实没有任何其他选择 - 内置实现会在无效 JSON 数据上引发异常,防止该异常停止您的应用程序的唯一方法是捕获它。即使使用第 3 方库也无法避免这种情况 - 他们必须在某处拨打 JSON.parse()
时拨打 try/catch
。
唯一的选择是实现您自己的 JSON 解析算法,该算法可能对无效数据结构更宽容,但这感觉就像用小核弹挖一个 1 立方米的洞。
关于性能的说明
Node.js cannot optimise 函数使用的 v8 JavaScript 引擎包含一个 try/catch
块。
更新: v8 4.5 and above can optimise 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 中的 every.single.statement 的 JavaScript 代码一次只执行一次,无论是从主函数调用还是从回调或来自不同的模块或其他。因此,每一条语句都会阻塞该过程。这不一定是坏事——一个设计良好的应用程序将花费大部分时间等待外部资源(数据库响应、HTTP 通信、文件系统操作等)。因此,非常重要的是 v8 引擎可以优化频繁执行的 JavaScript 代码,以便在这种阻塞状态下花费尽可能少的时间 - 请参阅有关性能的说明。
【讨论】:
感谢您提供这个非常简洁且写得很好的答案,特别是关于优化的一点。 为什么“1”可以解析json? 为了完整起见,需要注意的是,自从引入 TurboFan 编译器以来,V8 现在对 try-catch 进行了优化。 news.ycombinator.com/item?id=12178856【参考方案4】: var parsed;
try
parsed = JSON.parse(data);
catch (e)
parsed = JSON.parse(JSON.stringify(data));
root = parsed;
这对我有用。 在 Catch 中,我在将数据解析为 JSON 之前将其转换为字符串化。
【讨论】:
【参考方案5】:这是关于如何在异常期间不中断脚本
Promise.resolve((body)=>
let fbResponse = JSON.parse(body);
// some code for good
).catch(error =>
cl('Parsing error:');
cl(error);
// some code for bad
);
【讨论】:
以上是关于安全地处理节点中的错误 JSON.parse()的主要内容,如果未能解决你的问题,请参考以下文章
在 JSON.parse 的位置 0 处获取“SyntaxError:”JSON 中的意外标记”