给定一个JSON数据字符串,如何安全地将该字符串转换为JavaScript对象?
显然,我可以不安全地这样做:
var obj = eval("(" + json + ')');
但这让我很容易受到包含其他代码的JSON字符串的攻击,简单地评估似乎非常危险。
我不确定其他方法可以做到这一点,但这是你在原型(JSON教程)中如何做到这一点。
new Ajax.Request('/some_url', {method:'get',requestHeaders: {Accept: 'application/json'},onSuccess: function(transport){var json = transport.responseText.evalJSON(true);}});
使用true作为参数调用evalJSON()会清理传入的字符串。
evalJSON()
这个答案适用于IE<7,对于现代浏览器,请查看上面的Jonathan答案。
这个答案已经过时了,乔纳森在上面的答案(#0)现在是最好的答案.
JSON.org有许多语言的JSON解析器,包括四种不同的JavaScript解析器。我相信大多数人会认为json2.js是他们的goto实现。
如果您使用jQuery,您还可以使用:
$.getJSON(url, function(data) { });
然后你可以做这样的事情
data.key1.somethingdata.key1.something_else
等
$.ajax({url: url,dataType: 'json',data: data,success: callback});
回调传递返回的数据,这些数据将是由JSON结构定义并使用$.parseJSON()方法解析的JavaScript对象或数组。
$.parseJSON()
jQuery方法现在已弃用。改用此方法:
let jsonObject = JSON.parse(jsonString);
使用已弃用的jQuery功能的原始答案:
如果您使用jQuery,请使用:
jQuery.parseJSON( jsonString );
这正是你想要的(参见jQuery留档)。
#0是一种纯JavaScript方法,只要你能保证一个相当现代的浏览器。
这似乎是问题所在:
通过Ajax webSocket等接收的输入,它将采用String格式,但您需要知道它是否为JSON.parsable。问题是,如果您总是通过JSON.parse运行它,程序可能会继续“成功”,但您仍然会看到控制台中抛出一个错误,其中包含可怕的"Error: unexpected token 'x'"。
JSON.parsable
JSON.parse
"Error: unexpected token 'x'"
var data; try {data = JSON.parse(jqxhr.responseText);} catch (_error) {} data || (data = {message: 'Server error, please retry'});
使用“JSON.parse()”中的简单代码示例:
var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';var contact = JSON.parse(jsontext);
并扭转它:
var str = JSON.stringify(arr);
尝试将该方法与此Data对象一起使用。例如:Data='{result:true,count:1}'
Data='{result:true,count:1}
try {eval('var obj=' + Data);console.log(obj.count);}catch(e) {console.log(e.message);}
这种方法在Nodejs中确实有帮助,当您正在使用串行端口编程
只是为了好玩,这里有一种使用函数的方法:
jsonObject = (new Function('return ' + jsonFormatData))()
我找到了一个“更好”的方法:
在CoffeeScript中:
try data = JSON.parse(jqxhr.responseText)data ||= { message: 'Server error, please retry' }
在Javascript中:
使用JSON.parse可能是最好的方法。
这里有一个例子
var jsonRes = '{ "students" : [' +'{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +'{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +'{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';var studentObject = JSON.parse(jsonRes);
使用parse()方法的最简单方法:
parse()
var response = '{"result":true,"count":1}';var JsonObject= JSON.parse(response);
然后你可以得到JSON元素的值,例如:
var myResponseResult = JsonObject.result;var myResponseCount = JsonObject.count;
按照#0留档中的描述使用jQuery:
JSON.parse(jsonString);
JSON.parse()将传递给函数的任何JSON字符串转换为JSON对象。
JSON.parse()
为了更好地理解它,按F12在浏览器中打开“检查元素”,然后转到控制台编写以下命令:
var response = '{"result":true,"count":1}'; //sample json object(string form)JSON.parse(response); //converts passed string to JSON Object.
现在运行命令:
console.log(JSON.parse(response));
您将获得作为Object{result: true, count: 1}的输出。
{result: true, count: 1}
为了使用该Object,您可以将其分配给变量,也许是obj:
obj
var obj = JSON.parse(response);
通过使用obj和点(.)运算符,您可以访问JSON对象的属性。
.
尝试运行命令:
console.log(obj.result);
json.parse将变成对象。
JSON解析总是很痛苦。如果输入不如预期,它会抛出错误并使您正在做的事情崩溃。
您可以使用以下小函数来安全地解析您的输入。即使输入无效或已经是对象,它也会始终打开一个对象,这在大多数情况下更好:
JSON.safeParse = function (input, def) {// Convert null to empty objectif (!input) {return def || {};} else if (Object.prototype.toString.call(input) === '[object Object]') {return input;}try {return JSON.parse(input);} catch (e) {return def || {};}};
将对象转换为JSON,然后解析它,对我有用,例如:
JSON.parse(JSON.stringify(object))
您还可以使用reviver函数进行过滤。
reviver
var data = JSON.parse(jsonString, function reviver(key, value) {//your code here to filter});
有关更多信息,请阅读#0。
官方留档:
JSON.parse()方法解析JSON字符串,构造字符串描述的JavaScript值或对象。可以提供一个可选的reviver函数来在返回结果对象之前对其执行转换。
语法:
JSON.parse(text[, reviver])
参数:
text:要解析为JSON的字符串。有关JSON语法的描述,请参阅JSON对象。
text
reviver (optional):如果是函数,这规定了解析最初产生的值在返回之前如何转换。
reviver (optional)
返回值
与给定JSON文本对应的Object。
例外
如果要解析的字符串不是有效的JSON,则抛出Syn的错误异常。
老问题,我知道,但是没有人注意到这个解决方案使用new Function(),一个返回数据的匿名函数。
new Function()
举个例子:
var oData = 'test1:"This is my object",test2:"This is my object"'; if( typeof oData !== 'object' )try {oData = (new Function('return {'+oData+'};'))();}catch(e) { oData=false; } if( typeof oData !== 'object' ){ alert( 'Error in code' ); }else {alert( oData.test1 );alert( oData.test2 );}
这更安全一点,因为它在函数内部执行,不会直接在代码中编译。因此,如果里面有函数声明,它不会绑定到默认的窗口对象。
我用它来“编译”DOM元素的配置设置(例如数据属性)简单快捷。
试试这个。这个是用打字稿写的。
export function safeJsonParse(str: string) {try {return JSON.parse(str);} catch (e) {return str;}}
用JSON.parse()解析JSON字符串,数据变成JavaScript对象:
JSON.parse(jsonString)
这里,JSON表示处理JSON数据集。
假设我们从Web服务器收到以下文本:
'{ "name":"John", "age":30, "city":"New York"}'
解析为JSON对象:
var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');
这里obj是相应的JSON对象,如下所示:
{ "name":"John", "age":30, "city":"New York"}
要获取一个值,请使用.运算符:
obj.name // Johnobj.age //30
将JavaScript对象转换为带有JSON.stringify()的字符串。
JSON.stringify()
Javascript(浏览器和NodeJS)都有一个内置的JSON对象。在这个对象上有2种处理JSON的方便方法。它们如下:
JSON
除了非常方便地处理JSON之外,它们还可以用于其他手段。这两种JSON方法的组合使我们能够非常容易地制作数组或对象的深度克隆。例如:
let arr1 = [1, 2, [3 ,4]];let newArr = arr1.slice(); arr1[2][0] = 'changed';console.log(newArr); // not a deep clone let arr2 = [1, 2, [3 ,4]];let newArrDeepclone = JSON.parse(JSON.stringify(arr2)); arr2[2][0] = 'changed';console.log(newArrDeepclone); // A deep clone, values unchanged
如果我们有这样的字符串:
"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
然后我们可以简单地使用JSON.parse两次将此字符串转换为JSON对象:
var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"var jsonString= JSON.parse(sampleString)var jsonObject= JSON.parse(jsonString)
我们可以使用以下方法从JSON对象中提取值:
// instead of last JSON.parse:var { status, token } = JSON.parse(jsonString);
结果将是:
status = 1 and token = 65b4352b2dfc4957a09add0ce5714059
只是为了不同输入类型的封面解析
用JSON.parse()解析数据,数据就变成了一个JavaScript对象。
在派生自数组的JSON上使用JSON.parse()时,该方法将返回一个JavaScript数组,而不是JavaScript对象。
var myArr = JSON.parse(this.responseText);console.log(myArr[0]);
JSON中不允许日期对象。#36825;做这样的事情
var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';var obj = JSON.parse(text);obj.birth = new Date(obj.birth);
JSON中不允许使用函数。如果您需要包含一个函数,请将其写成字符串。
var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';var obj = JSON.parse(text);obj.age = eval("(" + obj.age + ")");
这个问题已经有了很好的答案,但我对性能很好奇,今天2020.09.21我在Chromev85、Safariv13.1.2和Firefox v80上对MacO HighSierra 10.13.6进行了测试,以选择解决方案。
eval/Function
eval
我执行4个测试用例:
上述测试中使用的对象来自这里
let obj_ShallowSmall = {field0: false,field1: true,field2: 1,field3: 0,field4: null,field5: [],field6: {},field7: "text7",field8: "text8",} let obj_DeepSmall = {level0: {level1: {level2: {level3: {level4: {level5: {level6: {level7: {level8: {level9: [[[[[[[[[['abc']]]]]]]]]],}}}}}}}}},}; let obj_ShallowBig = Array(1000).fill(0).reduce((a,c,i) => (a['field'+i]=getField(i),a) ,{}); let obj_DeepBig = genDeepObject(1000); // ------------------// Show objects// ------------------ console.log('obj_ShallowSmall:',JSON.stringify(obj_ShallowSmall));console.log('obj_DeepSmall:',JSON.stringify(obj_DeepSmall));console.log('obj_ShallowBig:',JSON.stringify(obj_ShallowBig));console.log('obj_DeepBig:',JSON.stringify(obj_DeepBig)); // ------------------// HELPERS// ------------------ function getField(k) {let i=k%10;if(i==0) return false;if(i==1) return true;if(i==2) return k;if(i==3) return 0;if(i==4) return null;if(i==5) return [];if(i==6) return {};if(i>=7) return "text"+k;} function genDeepObject(N) {// generate: {level0:{level1:{...levelN: {end:[[[...N-times...['abc']...]]] }}}...}}}let obj={};let o=obj;let arr = [];let a=arr; for(let i=0; i<N; i++) {o['level'+i]={};o=o['level'+i];let aa=[];a.push(aa);a=aa;} a[0]='abc';o['end']=arr;return obj;}
下面的代码片段提供了选择的解决方案
// src: https://stackoverflow.com/q/45015/860099function A(json) {return eval("(" + json + ')');} // https://stackoverflow.com/a/26377600/860099function B(json) {return (new Function('return ('+json+')'))()} // improved https://stackoverflow.com/a/26377600/860099function C(json) {return Function('return ('+json+')')()} // src: https://stackoverflow.com/a/5686237/860099function D(json) {return JSON.parse(json);} // src: https://stackoverflow.com/a/233630/860099function E(json) {return $.parseJSON(json)} // --------------------// TEST// -------------------- let json = '{"a":"abc","b":"123","d":[1,2,3],"e":{"a":1,"b":2,"c":3}}'; [A,B,C,D,E].map(f=> {console.log(f.name + ' ' + JSON.stringify(f(json)))})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>This shippet only presents functions used in performance tests - it not perform tests itself!
以下是chrome的示例结果
另一种选择
const json = '{ "fruit": "pineapple", "fingers": 10 }'let j0s,j1s,j2s,j3sconsole.log(`{ "${j0s="fruit"}": "${j1s="pineapple"}", "${j2s="fingers"}": ${j3s="10"} }`)
在JavaScript中解析JSON的推荐方法是使用JSON.parse()
#0 API是与ECMAScript 5一起引入的,此后按市场份额计算已在>99%的浏览器中实施。
jQuery曾经有一个#0函数,但它在jQuery 3.0中被弃用了。无论如何,在很长一段时间里,它只不过是JSON.parse()的包装器。
const json = '{ "city": "Boston", "population": 500000 }';const object = JSON.parse(json);console.log(object.city, object.population);
所有主流浏览器都支持JSON.parse吗?
基本上,是的(见参考)。