【问题标题】:Difference between JSON.parse() and eval()JSON.parse() 和 eval() 之间的区别
【发布时间】:2014-03-26 20:14:22
【问题描述】:

可能需要一名 Javascript 语言律师来处理这个问题:

var s1 = "{\"x\":\"y:z\"}"

var o = JSON.parse(s1)
var s2 = JSON.stringify(o)

$('span#s').text(s1);
$('span#s2').text(s2);

if (s1 === s2) {
    $('span#areEqual').text('s1 === s2')
} else {
    $('span#areEqual').text('s1 !== s2')
}

JSON.parse(s2) // okay

$('span#jsonParse').text("JSON.parse(s2) okay")

eval(s2) // bad mojo!

$('span#eval').text("eval(s2) okay")

eval("("+s2+")") // bad mojo, too! 
$('span#eval2').text("eval((s2)) okay")

evals1s2"("+s2+")" 上失败。

jsFiddle here.

【问题讨论】:

  • 如果你问为什么eval 给出一个 SyntaxError,那是因为该字符串不代表一个有效的 JavaScript 程序,而这正是 eval 所要求的。
  • @JeffLowery:不,JSON.parse() 是一个 JSON 解析器。它接受有效的 JSON,并不关心它是否是有效的 JS 程序。
  • @JeffLowery:没有。“文本必须用括号括起来,以避免在 JavaScript 语法中出现歧义。”
  • @JeffLowery:与您的说法相反,eval("("+s2+")") 不会失败。
  • 您将用括号包裹的那个放在已经失败的那个下面。抛出错误时停止执行。

标签: javascript json


【解决方案1】:

你的问题是你把两个不相关的东西混在一起了。

eval() 是内置的javascript函数,主要目的是解释javascript代码字符串(从而造成潜在的安全漏洞)

JSON.parse() 函数用于解析 JSON 字符串。尽管非常相似,但请不要误会,JSON 不是 Javascript,并且存在细微差别。 您不应该使用 eval() 来解析 JSON

What are the differences between JSON and JavaScript object?

【讨论】:

  • 我想说的不仅仅是“微小的差异”。
  • 这是一个很好的解释,但它与“...... JSON 是 JavaScript 的真子集”不相符(www.json.org)
  • 嗯,准确的引用是“它基于 JavaScript 编程语言的一个子集”......它是基于 != 在我看来是一个适当的子集。
【解决方案2】:

eval 不是一个表达式 - 我已经更新它来评估 eval(s2 === s1); 否则它将尝试并执行 eval 中的内容并停止执行。

【讨论】:

    【解决方案3】:

    当你使用 eval 解析 JSON 时,你需要用括号括起来你的表达式

    eval('(' + s2 + ')');
    

    jsfiddle

    【讨论】:

    • 做到了。没区别,它也失败了。
    【解决方案4】:

    eval() 尝试评估一段 JavaScript 代码。如果您创建了一个以相同文本开头的脚本文件,您将得到相同的错误。在这种情况下,我相信大括号表示复合语句,就像在 if 语句或 for 语句体中一样,但复合语句的开头是一个字符串,后跟一个冒号,这是无效的语法。

    如果您想要一个可以计算为对象的字符串,则必须将对象表达式括在括号中以明确表明它是一个表达式。但正如 apocalypz 所说,您不应该尝试评估 JSON。在很多层面上都是错误的。

    【讨论】:

    • 我不反对不使用 eval(),但试图理解似乎有冲突的信息。似乎正在发生的是 JSON.parse 正在清理输入。转义的引号会混淆 eval 解析,因为它看到的是这样的:{x:y:z}
    • @JeffLowery:不,这不是正在发生的事情。只需"{\"x\":1}",您就会得到相同的结果。我解释了这个答案中发生的事情——它根本没有被解释为对象表达式。为了使其解析为对象表达式,您需要将其括在括号中。
    • 不是 Javascript 对象?看起来像 JSON.parse(): > var s1 = "{\"x\":\"y:z\"}" undefined > var o = JSON.parse(s1) undefined > o Object {x: " y:z"}
    • @JeffLowery:你是来理解还是争论?因为你似乎忽略了人们在说什么。 JavaScript 是 JSON 的超集。它包括不在 JSON 中的东西。在这种情况下,您的字符串被解释为其他事物之一,而 JSON 将其解释为 JSON。它是一个有效的对象表达式,但在该上下文中它不会被解析为一个。
    • 我不是在忽视你,我是在努力理解。在此过程中,我一直在回复其他信息。
    【解决方案5】:

    查看规范中关于 JSON 和 eval 的内容 http://www.json.org/js.html 特别注意这部分

    eval 函数非常快。但是,它可以编译和执行 任何 JavaScript 程序,因此可能存在安全问题。指某东西的用途 当来源受信任且有能力时,会指示 eval。很多 使用 JSON 解析器更安全。在基于 XMLHttpRequest 的 Web 应用程序中, 仅允许与提供以下内容的同一来源进行通信 页面,所以它是可信的。但它可能没有能力。如果服务器 JSON 编码不严谨,或者不严谨 验证其所有输入,然后它可以提供无效的 JSON 文本 那可能带有危险的脚本。 eval 函数将 执行脚本,释放其恶意。

    JSON 只是一个 javascript 对象,仅此而已。有效的 javascript 可能包括函数、执行块等。如果您只是 eval() 一个字符串,它可能会对其进行编码。如果它只是 JSON,JSON 将解析,但您不能通过将其填充到 eval 中确定。例如

    var s = "(function(){ /* do badStuff */ return {s: 123, t: 456}; })()";
    var result = eval(s);
    

    会给你一个带有内容{s: 123, t: 456} 的变量result,但也会执行隐藏在你的函数中的任何代码。如果您从其他地方获取此输入,则代码可能正在执行并且实际上不会破坏您的任何内容。现在与JSON.parse 相同的示例

    var result = JSON.parse(s);
    

    它会抛出一个错误消息:

    Uncaught SyntaxError: Unexpected token ( 
    

    因此,即使有人试图潜入,解析也可以让您免于远程执行代码。

    【讨论】:

    • 是的,很好的建议。我正在破解一个快速原型,很长一段时间以来,我一直依赖于直接从 $.ajax 指定 JSON 类型的 JSON。我几乎从不使用 eval(),但这是我首先想到的。糟糕,糟糕的评估。
    【解决方案6】:

    $eval 会根据给定范围自动评估。

    例如:

    $scope.a = 2;
    var result = $scope.$eval('1+1+a');
    // result is 4
    

    $parse 不需要范围。它接受一个表达式作为参数并返回一个函数。可以使用可以解析局部变量的对象调用该函数:

    例如:

    var fn = $parse('1+1+a');
    var result = fn({ a: 2 });
    // result is 4
    

    【讨论】:

      【解决方案7】:

      如果您真的想要使用 eval 而不是 JSON.parse() 来解析 JSON,那么您应该编写类似

      var o2; // declare o2 out of eval in case of "use strict"
      eval("o2 = "+s1); // parse s1 and the assignment to the local o2
      console.log(o2); // enjoy the local variable :)
      
      ...
      

      【讨论】:

        猜你喜欢
        • 2015-11-10
        • 2022-01-25
        • 1970-01-01
        • 2015-06-29
        • 1970-01-01
        • 2021-04-30
        • 1970-01-01
        • 2010-12-23
        相关资源
        最近更新 更多