为啥使用 JSON.parse(decodeURIComponent(staticString))?

Posted

技术标签:

【中文标题】为啥使用 JSON.parse(decodeURIComponent(staticString))?【英文标题】:Why use JSON.parse(decodeURIComponent(staticString))?为什么使用 JSON.parse(decodeURIComponent(staticString))? 【发布时间】:2016-03-21 01:00:29 【问题描述】:

某些动态 Web 框架使用此代码片段

<script>
appSettings = JSON.parse(
   decodeURIComponent(
     "%7B%22setting1%22%3A%22foo%22%2C%22setting2%22%3A123%7D"));
</script>

他们试图用这段代码解决一个标准的 html5/javascript 问题吗?为什么不只是

<script>
appSettings = "setting1":"foo","setting2":123;
</script>

注意:这是动态生成的代码。我假设在服务器上他们正在做类似的事情

var settingsString = encodeURIComponent(JSON.stringify(settings));
var output = '<script>appSettings=JSON.parse(decodeURIComponent("' + 
             settingsString + 
             '"));</script>';

但它似乎也可以像这样工作

var settingsString = JSON.stringify(settings);
var output = '<script>appSettings=' + 
             settingsString + 
             ';</script>';

一个想法是后者可以包含代码,但它们是提供字符串的人,它不是用户数据,所以它们不可能是代码。加上在服务器上使用JSON.stringify 将删除所有代码。即使在客户端上,JSON.parseJSON.stringifyied 对象的简单 JSON.parse 也会阻止代码。

三重解析是否解决了具体问题?一次使用 JavaScript,一次使用 decodeURIComponent,一次使用 JSON.parse?

这不是一个基于意见的问题

问题是要解决什么问题。要么有问题正在解决,要么没有。回答这个问题不需要任何意见。例如,如果 JSON.stringify 有时碰巧发出无法解析的代码(据我所知,它不会,但如果有人知道得更好,那么这将是一个很好的答案)。

另请注意:我不是在问他们的框架为什么这样做。我在问标准 HTML5/JavaScript 中是否存在真正的问题正在解决。换句话说,我是否应该采用这种模式,因为如果我不这样做,我总有一天会遇到问题。

【问题讨论】:

我能想到为什么有人可能这样做的各种原因(虽然我能想到 (FSVO) 更好的方法来解决同样的问题),但你要求我们推测未知人的思维过程,这实际上是无法回答的。 @Quentin,不,我不是要你推测。要么有具体的客观原因,要么没有。这就是问题所在。它的具体客观原因是什么。解决什么问题。 AFAIK JSON 没有转义问题,因此三重解析是多余的。但我可能错了,所以这个问题。 您是否有理由拒绝提及执行此操作的框架?这将有助于找出原因。 这种编码的一个好处是如果你的 JSON 包含 HTML(例如关闭 &lt;/script&gt; 标签),浏览器会将其解释为 HTML。 @gman:告诉我们框架的名称可以让我们检查其来源并寻找确定的 cmets。 【参考方案1】:

三重解析是否解决了具体问题?

是的。您建议的解决方案有两个问题:

它被解析为 HTML。 &lt;/script&gt; 之类的内容可能会对内联脚本造成严重破坏。 它被解析为 JS。 Not all JSON strings are valid JS literals。

decodeURIComponent + JSON.parse 方法是一种粗略的解决方法,但看起来更像是一种快速修复而不是适当的解决方案。

【讨论】:

您能否详细说明为什么它是快速修复而不是适当的解决方案? 它不必要地扩大了大小,一次是为了将 JSON 嵌入到 JS 字符串中,一次是为了对所有内容进行 url 编码。只需转义有问题的字符(序列)就足够了。【参考方案2】:

@katspaugh 是正确的

测试

var settingString = JSON.stringify(
  "</script>":  "<script>bar=123</script>",
);

将上述示例的代码生成为

<script>
appSettings = "</script>":"<script>window.bar=123</script>"
</script>

无法解析为 HTML。在服务器上添加encodeURIComponent JSON.parse(decodeURIComponent(...)) 在客户端上修复该问题

【讨论】:

以上是关于为啥使用 JSON.parse(decodeURIComponent(staticString))?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 JSON.parse(decodeURIComponent(staticString))?

为啥 JSON.parse(['1234']) 返回 1234?

为啥 JSON.parse(['1234']) 返回 1234?

为啥 JSON.parse 会抛出跨域错误?

JSON.parse(message) 失败,但“https://jsonlint.com/”显示消息有效。为啥会这样?

为啥不 decodeURI("a+b") == "a b"?