JSON.parse()和eval()之间的区别

问题描述 投票:2回答:7

这个可能需要一个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

javascript json
7个回答
5
投票

你的问题是你混合了两个不相关的东西。

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

JSON.parse()函数用于解析JSON字符串。虽然非常相似,但不要弄错,JSON不是Javascript并且存在微小的差异。您不应该使用eval()来解析JSON

What are the differences between JSON and JavaScript object?


2
投票

$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

1
投票

当您使用eval解析JSON时,您需要用括号包装表达式

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

jsfiddle


1
投票

查看规范中关于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);

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

var result = JSON.parse(s);

它会抛出错误消息:

Uncaught SyntaxError: Unexpected token ( 

因此,即使有人试图将其隐藏起来,解析也会使您免于远程执行代码。


0
投票

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


0
投票

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

如果您想要一个可以计算对象的字符串,则必须将对象表达式括在括号中,以使其明确表示它是一个表达式。但正如apocalypz所说,你不应该试图评估JSON。这么多级别都是错的。


0
投票

如果你真的想用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 :)

...
© www.soinside.com 2019 - 2024. All rights reserved.