将对象字符串转换为JSON

167

如何使用JavaScript(或jQuery)将描述对象的字符串转换为JSON字符串?

例如:将此字符串转换为JSON字符串(不是有效的JSON字符串):

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"

转换成这个:

str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

如果可能的话,我希望避免使用eval()


你的字符串为什么一开始就不是有效的JSON格式?你是如何生成它的? - gen_Eric
2
字符串存储在 data 属性中,例如:<div data-object="{hello:'world'}"></div>,但我不想在 HTML 中使用单引号(因此可能不太可靠)。 - snorpey
5
@snorpey说:<div data-object='{"hello":"world"}'></div>是100%有效的HTML(单引号与信任有什么关系?)。如果您以这种方式做,您只需使用 JSON.parse 就可以正常工作。注意:键也需要加引号。 - gen_Eric
@Rocket,感谢您的努力!我只是想找到一种绕过在HTML(即使它是100%有效)和JSON符号中使用单引号的方法。 - snorpey
@snorpey:避免在HTML属性中放置JSON是一个解决方法。我猜你可以使用双引号,并转义JSON中的引号<div data-object="{\"hello\":\"world\"}"></div>。如果你不想在属性中使用有效的JSON,则必须自己制定格式并解析它。 - gen_Eric
这些只是提示而不是答案。- 您可以使用http://www.jsoneditoronline.org/来验证我的JSON。- 在从代码后台传递JSON字符串时,请注意添加适当的转义字符。 - user669915
20个回答

184

如果字符串来源可靠,可以使用 eval 然后将结果 JSON.stringify。像这样:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));
注意,当您对对象字面量进行eval操作时,必须将其包装在括号中,否则大括号将被解析为块而不是对象。
我也同意问题下的评论,最好一开始就将对象编码为有效的JSON,避免必须解析,编码,然后再次解析它。HTML支持单引号属性(只需确保在字符串内部HTML编码任何单引号)。

这没有意义,如果字符串来自可信源,为什么我们要将其转换而不是使其成为有效的JSON。 - allenhwkim
2
@allenhwkim 的想法是将无效的 JSON 转换为有效的 JSON,因此 eval 将字符串转换为 JavaScript 对象(只要字符串表示有效的 JavaScript 即可,即使它不是有效的 JSON)。然后,JSON.stringify 从对象转换回(有效的)JSON 字符串。如果字符串不来自受信任的来源,则调用 eval 是危险的,因为它可以运行任何 JavaScript,这可能会导致跨站点脚本攻击的可能性。 - Matthew Crumley
2
如果字符串是这样构造的,例如:var str = "(function() {console.log("bad")})()"; 那么eval在这种情况下仍然会做出不好的事情。 - Rondo
使用 eval() 将会执行 JS 代码。它很容易被滥用。 - FisNaN
@allenhwkim:我们从不相信任何来源。在IT领域,信任意味着反复核查、检查和再次检查。 - Laszlo Varga
语法错误:意外的标记 { - Urasquirrel

112

你的字符串不是有效的JSON,因此JSON.parse(或jQuery的$.parseJSON)无法工作。

一种方法是使用eval来"解析" "无效"的JSON,然后使用stringify将其"转换"为有效的JSON。

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
str = JSON.stringify(eval('('+str+')'));
我建议不要试图“修复”无效的JSON,而是一开始就使用有效的JSON。生成str时出了问题,应该在生成之前解决它,而不是之后再解决。 编辑:您在评论中提到这个字符串存储在数据属性中:
<div data-object="{hello:'world'}"></div>

我建议您在此处进行修复,以便它可以轻松地被JSON.parse解析。 首先,键和值都需要用双引号括起来。 它应该看起来像这样(在HTML中使用单引号属性是有效的):

<div data-object='{"hello":"world"}'></div>

现在,您可以直接使用JSON.parse(或jQuery的 $.parseJSON )。

var str = '{"hello":"world"}';
var obj = JSON.parse(str);

50

jQuery.parseJSON


str = jQuery.parseJSON(str)

编辑。前提是您拥有有效的 JSON 字符串。


1
我看到这个问题是关于如何将JSON字符串转换为对象的。 - user425367

43

通过使用new String(jsontext)将jsontext转换为String对象可能更好,可增强类型安全性。 - Fuzzy Analysis
@fuzzyanalysis:不,原始包装器永远不应该使用。 - Ry-
1
JSON.parse() 应该是被 @LouiseMcMahon 指定为正确答案。 - pixel 67

29

我希望这个小函数可以将无效的JSON字符串转换为有效的JSON字符串。

function JSONize(str) {
  return str
    // wrap keys without quote with valid double quote
    .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
    // replacing single quote wrapped ones to double quote 
    .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
}

结果

let invalidJSON = "{ hello: 'world',foo:1,  bar  : '2', foo1: 1, _bar : 2, $2: 3, 'xxx': 5, \"fuz\": 4, places: ['Africa', 'America', 'Asia', 'Australia'] }"
JSON.parse(invalidJSON) 
//Result: Uncaught SyntaxError: Unexpected token h VM1058:2
JSON.parse(JSONize(invalidJSON)) 
//Result: Object {hello: "world", foo: 1, bar: "2", foo1: 1, _bar: 2…}

我们正在尝试使用JSON.parse对b进行去评估化处理,这看起来是一个不错的解决方案。我们仍然需要手动处理常量替换,但至少这样可以避免出现问题。 - ravemir
1
几乎完美。当一个值中包含 : 时,它就无法工作。 - seler
eval是纯粹的恶魔,我认为这是正确的方式。 - Nicolas M. Pardo
绝对天才 - Jabster28

9

使用时需谨慎(由于 eval()):

function strToJson(str) {
  eval("var x = " + str + ";");
  return JSON.stringify(x);
}

称为:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );

3
对于匿名下投票者,我向你发起挑战,请提供更好的解决方案。另外,如果您能说明下投票的原因,那就更好了。 - Tomalak
2
@Rocket:啊,误解了。抱歉,我以为是你给我点的踩。 :) - Tomalak
2
@kuboslav 这段代码在IE7中无法工作,因为IE7不支持原生的JSON格式。只要使用json2.js,它就会开始正常工作。不要太心急。 - Tomalak
1
@Tomalak,你可以利用虚拟元素的onclick属性来实现相同的功能,因此eval()并不是唯一的方法(从技术上讲)。我留下了一个答案,展示这种替代方法在实践中的工作原理。 - csuwldcat
1
@Tomalak 如果我们想要非常技术化,eval() 是调用 JS 引擎来解析和运行脚本内容的方法,每个文本代码片段(例如 onclick 等)或脚本标签都会调用支持 eval() 的相同基本机制。文本脚本标签、属性和新函数创建可以提供的一个好处是它们通常更容易优化(一旦转换并缓存),以便重复使用。不过,使用 eval() 不断重新评估相同的文本代码字符串要以同样的方式进行优化就困难得多了。由于 OP 要求不明确使用 eval(),我认为我提供的解决方案符合要求。 - csuwldcat
显示剩余13条评论

4

免责声明:请不要在家里尝试此操作,或用于需要其他开发人员认真对待的事情:

JSON.stringify(eval('(' + str + ')'));

好的,我完成了。
尽量不要使用eval,因为它对你来说是有害的。如上所述,对于较旧的浏览器(IE7及以下版本),请使用Crockford的JSON shim。

此方法需要您的字符串是有效的javascript,它将被转换为可以序列化为JSON的javascript对象。

编辑:按照Rocket的建议进行了修正。


应该是 JSON.stringify(eval('('+str+')'));,虽然我不赞成使用 eval,但他的字符串不是有效的 JSON,所以 JSON.parse 无法工作。 - gen_Eric

4
我为对这个旧帖子感兴趣的人提供了答案。
我创建了HTML5 data-*解析器的jQuery插件和演示,可以将格式不正确的JSON字符串转换为JavaScript对象,而不使用eval()
它可以通过以下HTML5 data-*属性:
<div data-object='{"hello":"world"}'></div>
<div data-object="{hello:'world'}"></div>
<div data-object="hello:world"></div>

进入对象:

{
    hello: "world"
}

3
你需要使用 "eval",然后使用 JSON.stringify 和 JSON.parse 处理结果。
 var errorString= "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
 var jsonValidString = JSON.stringify(eval("(" + errorString+ ")"));
 var JSONObj=JSON.parse(jsonValidString);

enter image description here


3

使用new Function()比eval更好,但仍应仅在输入安全的情况下使用。

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

console.log(parseJSON("{a:(4-1), b:function(){}, c:new Date()}"))
// outputs: Object { a: 3, b: b(), c: Date 2019-06-05T09:55:11.777Z }

来源: MDN2ality


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接