JSON.parse
与eval
和能将一个字符串解析成一个JSON
对象,但还是有挺大区别。
测试代码
var A = "{ a: 1 , b : 'hello' }";
var B = "{ 'a': 1 , 'b' : 'hello' }";
var C = "{'a':1,'b':'hello'}";
var D = '{"a":1,"b":"hello"}';
var E = '{ "a" : 1 , "b" : "hello" }';
var F = '{ "a" : 1 ,\n "b" : "hello" }';
var G = '{ "a" : 1 , "b" : window.location.href="https://www.baidu.com" }';
JSON.parse
执行:
例:JSON.parse(A);
A、B、C、G都不可转,D、E、F都可以。
eval
执行:
例:eval("("+A+")");
A到G都可以转,特别到G时,页面还跳转到百度了。
JSON.parse
上面的演示例子可以看出,这方法只能解析属性名是双引号包裹的字符串对象,并会忽略换行和空格(值外面)。
但是,从MDN对JSON
的描述,能解析的JSON
字符串的条件完整如下:
JavaScript类型 | JSON与之区别 |
---|---|
对象和数组 | 属性名称必须用双引号包裹; |
最后一个属性后面不能有逗号。 | |
数值 | 前导0不能使用(在 JSON.stringify 中将会被忽略,在 JSON.parse 会抛出错误); |
小数点后面至少有一个数字。 | |
字符串 | 只有有限的字符能够被转义; |
不允许某些控制字符;但允许使用Unicode 行分隔符 (U+2028) 和段落分隔符 (U+2029) ; |
|
字符串必须用双引号括起来。 |
这方法还可以捕捉JSON中的语法错误,并允许你传入一个函数,用来过滤或转换解析结果。
浏览器兼容:IE8+
eval
eval
函数可将一个JavaScript代码字符串求值成特定的对象,所以解析成JSON对象只不过是作用之一。
为什么eval()解析JSON字符串要加上括号?
原因是两点:
json
对象是以”{}
”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理。加上圆括号为了处理字符串为表达式,而不是语句(
statement
)来执行。
例子:
对象字面量 {}
,不加外层的括号,那么eval会识别为JS代码块的开始和结束标记,那么 {}
将会被认为是执行了一句空语句。
alert(eval("{}")); // return undefined
alert(eval("({})"));// return object[Object]
不建议使用
虽然从演示例子看,eval
的能力是强过于JSON.parse
的,它可解析不规范的JSON
字符串,但是G的例子也可以看出,eval
是不安全的,特别是数据是第三方给予时候,你根本不知道eval
之后它会干什么。
所以结论就是,乖乖用JSON.parse
解析JSON
对象。
$.parseJSON
jQuery也有提供解析JSON
字符串的方法,$.parseJSON
,就目前jQuery版本来讲,分为两类。
2.x和3.x版本: $.parseJSON
都是直接使用 JSON.parse
的。
1.x版本:浏览器支持 JSON.parse
就用这个,不支持就进行校验,确认是JSON字符串,则用
( Function( "return " + str ) )()
返回对象,否则返回无效JSON
对象error
。
PS:之所以能用Function
处理,前提是校验确认为JSON字符串,不然还是不安全的转换方法。
总结
eval
是强烈不建议用来解析JSON
字符串,但是凡事无绝对,如果数据来源于你信任的并且格式也不大规范,那用它也不是不可以。
eval()
和JSON.parse()
的区别
我们将一个字符串解析成json
对象时可以使用两种方法:
假设我们有一个json
格式的字符串:
'{
"student" : [
{"name":"鸣人","age":17},
{"name":"小樱","age":17},
{"name":"佐助","age":17}
]
}'
然后我们需要把它解析成json
对象
1、eval()
代码如下:
var data = '{"student" : [{"name":"鸣人","age":17}, {"name":"小樱","age":17},{"name":"佐助","age":17}]}';
eval('(' + data + ')');
2、JSON.parse()
代码如下:
var data = '{"student" : [{"name":"鸣人","age":17}, {"name":"小樱","age":17},{"name":"佐助","age":17}]}';
JSON.parse(data);
区别:eval
方法不会去检查给的字符串时候符合json
的格式~同时如果给的字符串中存在js
代码eval
也会一并执行~比如如果上面的json
格式的字符串改为:(注意红色部分)
var data = '{"student" : [{"name":"鸣人","age":17}, {"name":"小樱","age":alert("hehe")},{"name":"佐助","age":17}]}';
此时执行eval
方法后会先弹出一个提示框输出hehe的字符串~
但是使用JSON.parse()
就会报错~显示错误信息为当前字符串不符合json
格式~即JSON.parse()
方法会检查需要转换的字符串是否符合json
格式~
相比较而言eval
方法是很危险的~特别是当涉及到第三方时我们需要确保传给eval
的参数是我们可以控制的~不然里面插入比如window.location
~指向一个恶意的连接~那叫叫天啦
从这个层面讲~还是推荐使用JSON.parse
来实现json
格式字符串的解析
考虑到我们在制造json
格式的字符串时极易出现错误~这里推荐一个json
格式字符串的在线校验工具:http://jsonlint.com/