安全地将JSON字符串转换为对象


1334

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

显然,我可以通过以下方式不安全地执行此操作:

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

但这使我容易受到包含其他代码的JSON字符串的影响,仅进行评估似乎很危险。


77
在大多数语言中,评估都带来额外的风险。Eval敞开了大门,可供黑客利用。但是,请记住,所有JavaScript都在客户端上运行。 的处置,这将被黑客修改。他们只需使用控制台就可以评估所需的任何东西。您必须在服务器端建立保护。
海滨别墅

19
好的,现在是2014年,您永远不要使用eval它来解析JSON字符串,因为您会将代码暴露给“代码注入”。使用JSON.parse(yourString)代替。
丹尼尔(Daniel)

JSON数据是文字吗?
shanechiu

@shanechiu:如果要表示标量数据类型,是的。只是其中包含键值语法的字符串。
下午0zkr下午

Answers:


1960

JSON.parse(jsonString) 只要您可以保证使用合理的现代浏览器,它就是一种纯JavaScript方法。


74
我很确定它对于Node.js是安全的
Stephen

76
@vsync您确实意识到这是唯一的纯Java答案...如果您阅读javascript标记的说明,您将看到此...“ 除非也包含框架/库的标记,否则纯JavaScript答案是。预期 ”。我给这+1为是唯一的JavaScript的答案...
iConnor


12
如果您正在使用NodeJS,则无法加载jQuery只是将JSONString解析为JSON对象。因此支持乔纳森(Jonathan)的答案
安东尼

6
根据该链接,它受IE8 +的支持,尽管它说:Requires document to be in IE8+ standards mode to work in IE8.
JoshuaDavid

878

现在不推荐使用jQuery方法。请改用此方法:

let jsonObject = JSON.parse(jsonString);

使用不推荐使用的jQuery功能的原始答案

如果您使用的是jQuery,请使用:

jQuery.parseJSON( jsonString );

正是您要找的东西(请参阅jQuery 文档)。


7
是否有理由在JSON.parse()上使用它?
乔恩

8
jQuery.parseJSON默认情况下使用(JSON.parse如果存在),因此在实际环境中使用它的唯一原因是是否需要<IE7的后备。在jQuery 1.6中已进行了更改:james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
Karl-

9
2016年更新:自jQuery 3.0起,不推荐使用$ .parseJSON,而应使用本机JSON.parse方法。
jkdev

159

该答案适用于IE <7,对于现代浏览器,请查看上面的Jonathan答案。

这个答案已经过时了,乔纳森JSON.parse(jsonString)以上的答案现在是最好的答案

JSON.org具有用于多种语言的JSON解析器,包括用于JavaScript的四种不同语言。我相信大多数人都会将json2.js视为其goto实现。


24
我希望人们不要再对此答案投反对票。它在2008年发布时是准确的。只需对新版本进行投票。
约翰

22
如果答案现在已过时,请考虑对其进行更新。
Sotirios Delimanolis 2015年

2
对于IE <8,您需要使用它。
Mahmoodvcs 2015年

74

使用“ JSON.parse() ”中的简单代码示例:

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

并反转:

var str = JSON.stringify(arr);

23

我不确定其他实现方法,但是这是您在Prototype(JSON教程)中的实现方法

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

调用evalJSON()与真正作为参数进行消毒传入的字符串。


22

这似乎是问题所在:

通过Ajax websocket等接收到的输入,它将采用String格式,但是您需要知道它是否为JSON.parsable。麻烦的是,如果始终运行它JSON.parse,则程序可以“成功”继续运行,但是您仍然会在控制台中看到带有dreaded 的错误"Error: unexpected token 'x'"

var data;

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

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

没有。问题是您期望使用JSON对象,并且(function(){ postCookiesToHostileServer(); }());在Node上下文中可能会出现甚至是更讨厌的东西。
Yaur 2014年

好的JSON.parse可以清理函数的输入(在这种情况下,它作为IIF->对象是没有用的)。似乎解决该问题的最佳方法是尝试/捕获。(查看修改)
Cody 2014年

18

如果您使用的是jQuery,则还可以使用:

$.getJSON(url, function(data) { });

然后你可以做类似的事情

data.key1.something
data.key1.something_else

等等


您正在使用jQuery,不是吗?
Alexandre C.

15
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

回调将传递返回的数据,该数据将是由JSON结构定义并使用$.parseJSON()方法解析的JavaScript对象或数组。


12

只是为了好玩,这是使用函数的一种方式:

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

1
有趣的方法,我不确定是否可以将其与JSON.Parse一起使用,但是很高兴看到有人在框外思考。

5
这与仅使用eval它非常相似,并且不安全。:P
Florrie

7
这具有使用的所有缺点,eval但是对于维护人员来说更复杂和更难理解。
昆汀2015年

9

使用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);

9

最简单的使用parse()方法:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

然后,您可以获取JSON元素的值,例如:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

如文档中所述使用jQueryjQuery.parseJSON()

JSON.parse(jsonString);

9

尝试将此方法与此Data对象一起使用。例如:Data='{result:true,count:1}

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

您进行串行端口编程时,此方法确实对Node.js 帮助


这实在是让人感到滑稽如何固定到“EVAL是邪恶的”,他们会尽一切努力避免它,甚至重写整个EVAL-功能..
diynevala

共识是这个技巧是将字符串转换为JSON对象的安全方法吗?我可以使用它,因为不需要其他js导入。
Whome

1
使用evalFunction同样容易受到攻击的任何方法
Slai

undefined; function bye() {...} bye();
Salvioner '19

5

我发现了一种“更好”的方式:

在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'
});

4

JSON解析总是很痛苦。如果输入与预期不符,则会引发错误并使您正在执行的操作崩溃。

您可以使用以下微型函数安全地解析您的输入。即使输入无效或已经是大多数情况下更好的对象,它总是会旋转一个对象:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};

Object.prototype.toString.call(input) === '[object Object]'应该是typeof input === 'object'IMO
SergeK。17年

typeof输入也会返回null和数组的对象。因此,这不是安全的方法。
塔欣

null之前已经介绍过该案例,并且数组一个Object。如果要测试,可以使用instanceof。而且,如果给此函数一个Array,它将捕获并return def可能返回完美的数组。
Serge K.

我的评论是关于捕捉物体时的常识。我的函数可以采取多种预防措施,但一般而言,使用typeof输入不是检测对象的首选方法。
塔欣

IMO,常识不使用toString()方法来检查变量是否是对象。参见AngularJSjQueryUnderscore甚至开发人员
SergeK。18年


3

如果我们有这样的字符串:

"{\"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

3

JSON.parse() 将传递给函数的所有JSON字符串转换为JSON对象。

为了更好地理解它,请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));

您将获得作为对象的输出 {result: true, count: 1}

为了使用该对象,您可以将其分配给变量,也许是obj

var obj = JSON.parse(response);

通过使用obj和点(.)运算符,您可以访问JSON对象的属性。

尝试运行命令:

console.log(obj.result);

3

官方文件

JSON.parse()方法解析JSON字符串,构造JavaScript值或该字符串描述的对象。reviver可以提供一个可选函数,以在返回结果对象之前对其进行转换。

句法:

JSON.parse(text[, reviver])

参数:

text :要解析为JSON的字符串。有关JSON语法的描述,请参见JSON对象。

reviver (optional) :如果是函数,则此函数规定了在返回之前如何转换最初由解析产生的值。

返回值

与给定JSON文本相对应的Object。

例外情况

如果要解析的字符串无效的JSON,则引发SyntaxError异常。



2

使用解析JSON字符串JSON.parse(),数据成为一个JavaScript对象:

JSON.parse(jsonString)

在这里,JSON表示要处理JSON数据集。

假设我们从网络服务器收到了以下文本:

'{ "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 // John
obj.age //30

使用将JavaScript对象转换为字符串JSON.stringify()


1

只是为了掩盖解析不同的输入类型

使用JSON.parse()解析数据,该数据成为JavaScript对象。

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

在从数组派生的JSON上使用JSON.parse()时,该方法将返回JavaScript数组,而不是JavaScript对象。

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

JSON中不允许使用日期对象。对于日期,要做这样的事情

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 + ")");

0

我知道较旧的问题,但是没有人注意到使用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元素(例如data属性)的配置设置。


0

摘要:

Javascript(浏览器和NodeJS)都有一个内置JSON对象。在此Object上有2种方便的处理方法JSON。它们是:

  1. JSON.parse() 需要JSON作为参数,返回JS对象
  2. JSON.stringify() 将JS对象作为参数返回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


0

您也可以使用reviver功能进行过滤。

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

有关更多信息,请阅读JSON.parse


0

JSON.parse是将字符串转换为对象的正确方法,但是如果所解析的字符串不是对象或字符串不正确,则将抛出错误,导致其余代码中断,因此将JSON.parse函数包装在try-catch中的理想选择

try{
   let obj = JSON.parse(string);
}catch(err){
   console.log(err);
}

-1

试试这个。这是用打字稿写的。

         export function safeJsonParse(str: string) {
               try {
                 return JSON.parse(str);
                   } catch (e) {
                 return str;
                 }
           }

我是Typescript的新手。这有什么好处JSON.parse()
Marc L.

如果发生任何异常,这将返回输入字符串本身
Supun Dharmarathne '18

-1
/**
 * Safely turning a JSON string into an object
 *
 * @param {String} str - JSON String
 * @returns deserialized object, false if error
 */
export function jsonParse(str) {
  let data = null;
  try {
    data = JSON.parse(str);
  } catch (err) {
    return false;
  }
  return data;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.