给定一个JSON数据字符串,如何安全地将该字符串转换为JavaScript对象?

很明显,我可以用这样的方式来做这件事:

var obj = eval("(" + json + ')');

但这让我很容易受到包含其他代码的JSON字符串的攻击,简单地eval似乎非常危险。


当前回答

jQuery方法现在已被弃用。请改用此方法:

let jsonObject = JSON.parse(jsonString);

使用已弃用的jQuery功能的原始答案:

如果您使用jQuery,只需使用:

jQuery.parseJSON( jsonString );

这正是您想要的(请参阅jQuery文档)。

其他回答

为了好玩,这里有一种使用函数的方法:

 jsonObject = (new Function('return ' + jsonFormatData))()

只要你能保证一个相当现代的浏览器,JSON.parse(jsonString)就是一种纯JavaScript方法。

表演

这个问题已经有了很好的答案,但我对性能很好奇,今天2020.09.21我在Chrome v85、Safari v13.1.2和Firefox v80上对MacOs HighSierra 10.13.6进行了测试,以确定所选的解决方案。

后果

eval/Function(A,B,C)方法在Chrome上很快(但对于大深度对象N=1000,它们会崩溃:“最大堆栈调用超过”)eval(A)在所有浏览器上都是快速/中等速度JSON.parse(D,E)在Safari和Firefox上速度最快

细节

我执行4个测试用例:

对于小的浅对象对于这里的小深对象对于这里的大型浅层物体对于这里的大深度对象

上述测试中使用的对象来自HERE

let obj_ShallowSmall={字段0:假,字段1:真,字段2:1,字段3:0,字段4:空,字段5:[],字段6:{},field7:“text7”,字段8:“text8”,}让obj_DepSmall={级别0:{级别1:{级别2:{级别3:{级别4:{级别5:{级别6:{第7级:{级别8:{第9级:[[[[[[[[]],}}}}}}}}},};让obj_ShallowBig=数组(1000).fill(0).reduce((a,c,i)=>(a['field'+i]=getField(i),a),{});让obj_DepBig=genDeepObject(1000);// ------------------//显示对象// ------------------console.log('obj_ShallowSmall:',JSON.stringify(obj_SharlowSmall));console.log('obj_DepSmall:',JSON.stringify(obj_DeepSmall));console.log('obj_ShallowBig:',JSON.stringify(obj_SharlowBig));console.log('obj_DepBig:',JSON.stringify(obj_DeepBig));// ------------------//助手// ------------------函数getField(k){设i=k%10;如果(i==0)返回false;如果(i==1)返回真;如果(i==2)返回k;如果(i==3)返回0;如果(i==4)返回null;如果(i==5)返回[];如果(i==6)返回{};如果(i>=7)返回“text”+k;}函数genDeepObject(N){//生成:{level0:{level1:{…levelN:{end:[[[…N次…['abc']…]]}}}}…}}让obj={};设o=obj;设arr=[];设a=arr;for(设i=0;i<N;i++){o['level'+i]={};o=o['level'+i];设aa=[];a.推(aa);a=aa;}a[0]=“公元前”;o['end']=arr;返回obj;}

下面的片段显示了所选的解决方案

//第三节:https://stackoverflow.com/q/45015/860099函数A(json){return eval(“(”+json+')');}// https://stackoverflow.com/a/26377600/860099函数B(json){return(新函数('return('+json+')'))()}//改进的https://stackoverflow.com/a/26377600/860099函数C(json){return函数('return('+json+')')()}//第三节:https://stackoverflow.com/a/5686237/860099函数D(json){返回JSON.parse(JSON);}//第三节:https://stackoverflow.com/a/233630/860099函数E(json){return$.parseJSON(json)}// --------------------//测试// --------------------让json=“{“a”:“abc”,“b”:“123”,“d”:[1,2,3],“e”:{”a“:1,”b“:2,”c“:3}}”;[A,B,C,D,E]映射(f=>{控制台日志(f.name+“”+JSON.stringfy(f(JSON)))})<script src=“https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js“></script>此shippet只显示性能测试中使用的函数,而不执行测试本身!

下面是铬的示例结果

我找到了一个“更好”的方法:

在CoffeeScript中:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

在Javascript中:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});

在JavaScript中解析JSON的推荐方法是使用JSON.parse()

出身背景

JSON API是在ECMAScript 5中引入的,目前已在99%以上的浏览器中实现(按市场份额)。

jQuery曾经有一个$.parseJSON()函数,但在jQuery 3.0中已弃用。无论如何,在很长一段时间里,它只是JSON.parse()的包装器。

实例

const json=“{”城市“:”波士顿“,”人口“:500000}”;const object=JSON.parse(JSON);console.log(object.city,object.population);


浏览器兼容性

所有主要浏览器都支持JSON.parse吗?

差不多,是的(见参考资料)。