ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

但这让我容易受到包含其他代码的 JSON 字符串的影响,简单地评估似乎非常危险。

在大多数语言中,eval 带有额外的风险。 Eval 为黑客的利用敞开了大门。但是,请记住所有 javascript 都在客户端上运行。预计它将被黑客更改。他们可以 EVAL 任何他们想要的东西,只需使用控制台。您必须在服务器端建立保护。
好的,现在是 2014 年,您永远不应该使用 eval 来解析 JSON 字符串,因为您会将代码暴露给“代码注入”。请改用 JSON.parse(yourString)
JSON数据是文字吗?
@shanechiu:如果您的意思是标量数据类型,是的。只是一个带有键值语法的字符串。
请参阅有关 parse() 方法的文档:w3schools.com/js/js_json_parse.asp

G
Graham

JSON.parse(jsonString) 是一种纯 JavaScript 方法,只要您可以保证是相当现代的浏览器。


我很确定它对 Node.js 是安全的
@vsync 您确实意识到这是唯一的纯 JavaScript 答案...如果您阅读 javascript 标签的描述,您会看到这个...“除非还包括框架/库的标签,否则纯 JavaScript 答案是预期。” ..我给这个+1是唯一的javascript答案...
如果您正在使用 NodeJS,那么我无法加载 jQuery 来将 jsonString 解析为 JSON 对象。所以赞成乔纳森的回答
根据 this link,IE8+ 支持它,虽然它说:Requires document to be in IE8+ standards mode to work in IE8.
Q
Quentin

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

let jsonObject = JSON.parse(jsonString);

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

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

jQuery.parseJSON( jsonString );

这正是您正在寻找的(参见 jQuery documentation)。


有理由在 JSON.parse() 上使用它吗?
jQuery.parseJSON 如果存在则默认使用 JSON.parse,因此使用它而不是真实的唯一原因是如果您需要 <IE7 的后备。它在 jQuery 1.6 中被改变了:james.padolsey.com/jquery/#v=1.6.0&fn=jQuery.parseJSON
2016 年更新:从 jQuery 3.0 开始,$.parseJSON 已弃用,您应该改用本机 JSON.parse 方法。
t
the Tin Man

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

此答案已过时,Jonathan's answer above (JSON.parse(jsonString)) 现在是最佳答案

JSON.org 具有多种语言的 JSON 解析器,包括四种不同的 JavaScript 解析器。我相信大多数人会考虑 json2.js 他们的 goto 实现。


我希望人们停止对这个答案投反对票。它在 2008 年发布时是准确的。只需支持新的。
如果答案现在已经过时,请考虑更新它。
对于 IE < 8,您需要使用它。
t
the Tin Man

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

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

并扭转它:

var str = JSON.stringify(arr);

t
the Tin Man

这似乎是一个问题:

通过 Ajax websocket 等接收的输入,它将是字符串格式,但您需要知道它是否为 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 对象,并且在 Node.js 的上下文中可能会出现 (function(){ postCookiesToHostileServer(); }()); 甚至更糟糕的东西。
那么 JSON.parse 会清除函数的输入(在这种情况下,作为 IIF --> 对象将无济于事)。似乎解决这个问题的最好方法是尝试/捕捉。 (见编辑)
t
the Tin Man

我不确定其他方法,但这是您在 Prototype (JSON tutorial) 中的方法。

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

使用 true 作为参数调用 evalJSON() 会清理传入的字符串。


t
the Tin Man

如果您使用 jQuery,您还可以使用:

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

然后你可以做类似的事情

data.key1.something
data.key1.something_else

等等


你正在使用 jQuery,不是吗?
t
the Tin Man

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

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

有趣的方法,我不确定我是否会在可用的 JSON.Parse 中使用它,但很高兴看到有人跳出框框思考。
这与仅使用 eval 执行此操作非常相似,并且不安全。 :P
这具有使用 eval 的所有缺点,但更复杂,维护者更难理解。
h
hexacyanide
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

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


J
Jean-François Fabre

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

G
GPrathap

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

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

当您使用串行端口编程时,此方法在 Nodejs 中确实很有帮助


人们如何执着于“评估是邪恶的”真的很有趣,他们会做任何事情来避免它,甚至重写整个评估功能。
共识这个技巧是将字符串转换为 JSON 对象的安全方法吗?我可以使用它,因为不需要额外的 js 导入。
使用 evalFunctionANY 方法同样容易受到攻击
undefined; function bye() {...} bye();
t
the Tin Man

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

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

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

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

按照 jQuery.parseJSON() 文档中的说明使用 jQuery

JSON.parse(jsonString);

D
Dorian

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

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

t
the Tin Man

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
typeof 输入也为 null 和数组返回对象。因此,这样做不是安全的方法。
您之前已经介绍过 null 的情况,并且数组 is 是一个对象。如果你想测试它,你可以使用instanceof。此外,如果你给这个函数一个 Array,它会在它可以返回完美的数组时捕获和 return def
我的评论是关于捕捉物体时的常识。我的功能可以有几个预防措施,但使用 typeof 输入通常不是检测对象的首选方式。
IMO,常识不使用 toString() 方法来检查变量是否是对象。请参阅 AngularJSjQueryUnderscore 甚至 devs
t
the Tin Man

使用 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 // John
obj.age //30

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


S
Shekhar Tyagi
JSON.parse(jsonString);

json.parse 将变为对象。


t
the Tin Man

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

为了更好地理解它,请按 F12 在浏览器中打开“Inspect Element”并转到控制台编写以下命令:

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

t
the Tin Man

官方文档:

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

句法:

JSON.parse(text[, reviver])

参数:

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

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

返回值

与给定 JSON 文本对应的 Object。

例外

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


S
Sebyddd

将对象转换为 JSON,然后对其进行解析,对我有用,例如:

JSON.parse(JSON.stringify(object))

t
the Tin Man

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

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

K
Kamil Kiełczewski

表现

这个问题已经有了很好的答案,但是我对性能很好奇,今天 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 上最快

https://i.stack.imgur.com/Wzn1w.png

细节

我执行 4 个测试用例:

对于小的浅物体在这里

对于小的深物体在这里

对于大的浅物体在这里

大深物体在这里

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

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']]]]]]] ]]], }}}}}}}}}, };让 obj_ShallowBig = Array(1000).fill(0).reduce((a,c,i) => (a['field'+i]=getField(i),a) ,{});让 obj_DeepBig = genDeepObject(1000); // ------------------ // 显示对象 // ------------------ 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)); // ------------------ // 帮助 // ------------------ function getField(k) { let我=k%10;如果(i==0)返回假;如果(i==1)返回真; if(i==2) 返回 k;如果(i==3)返回 0; if(i==4) 返回空值; if(i==5) 返回 []; if(i==6) 返回 {};如果(i>=7)返回“文本”+k; } function genDeepObject(N) { // 生成:{level0:{level1:{...levelN: {end:[[[...N-times...['abc']...]]] } }}...}}} 让 obj={};让 o=obj;让 arr = [];让 a=arr; for(让 i=0; i

下面的片段展示了选择的解决方案

// src: https://stackoverflow.com/q/45015/860099 function A(json) { return eval("(" + json + ')'); } // https://stackoverflow.com/a/26377600/860099 function B(json) { return (new Function('return ('+json+')'))() } // 改进 https://stackoverflow. com/a/26377600/860099 function C(json) { return Function('return ('+json+')')() } // src: https://stackoverflow.com/a/5686237/860099 function D(json ) { 返回 JSON.parse(json); } // src: https://stackoverflow.com/a/233630/860099 function 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].map(f=> { console.log( f.name + ' ' + JSON.stringify(f(json)) )}) 这个shippet只展示了性能测试中使用的函数——它本身不执行测试!

这是 chrome 的示例结果

https://i.stack.imgur.com/mzfaY.png


C
Codebeat

老问题,我知道,但是没有人通过使用 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 );
      }

这更安全一些,因为它在函数内部执行,而不是直接在您的代码中编译。所以如果里面有函数声明,就不会绑定到默认的window对象。

我使用它来简单快速地“编译”DOM 元素(例如数据属性)的配置设置。


W
Willem van der Veen

概括:

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

JSON.parse() 以 JSON 为参数,返回 JS 对象 JSON.stringify() 以 JS 对象为参数,返回 JSON 对象

其他应用:

除了非常方便地处理JSON之外,它们还可以用于其他方式。两种 JSON 方法的组合使我们能够非常轻松地对数组或对象进行深度克隆。例如:

让 arr1 = [1, 2, [3 ,4]];让 newArr = arr1.slice(); arr1[2][0] = '改变';控制台.log(newArr); // 不是深度克隆 let arr2 = [1, 2, [3 ,4]];让 newArrDeepclone = JSON.parse(JSON.stringify(arr2)); arr2[2][0] = '改变'; console.log(newArrDeepclone); // 深度克隆,值不变


t
the Tin Man

您也可以使用 reviver 函数进行过滤。

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

有关详细信息,请阅读 JSON.parse


M
MOnkey

只是针对不同输入类型的封面解析

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

山茶树和葡萄树
/**
 * 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;
}

b
bdkopen

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

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

我是打字稿的新手。这对 JSON.parse() 有什么好处?
如果发生任何异常,这将返回输入字符串本身
@MarcL。据我所知,TypeScript 不会修改 JSON.parse() 和任何其他系统方法(但我没有在这个方向进行研究)