将对象字符串转换为JSON


165

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

例如:转换这个(不是有效的JSON字符串):

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

到这个:

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

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


为什么字符串首先是无效的JSON?您是如何产生的?
火箭Hazmat 2012年

2
字符串存储在data-attrubute中,如下所示:<div data-object="{hello:'world'}"></div>而且我不想在HTML中使用单引号(因此可能不值得信任)
snorpey 2012年

5
@snorpey:<div data-object='{"hello":"world"}'></div>100%有效的HTML(单引号与信任它有什么关系?)。如果您采用这种方式,就可以JSON.parse做到,而且效果很好。 注意:键也需要加引号。
火箭Hazmat 2012年

@Rocket感谢您的努力!我只是想找到一种方法,必须在HTML中使用单引号(即使100%有效)和JSON表示法。
snorpey 2012年

@snorpey:解决方法不是首先将JSON放在HTML属性中。我猜您可以使用双引号并将JSON中的引号转义<div data-object="{\"hello\":\"world\"}"></div>。如果您不想在属性中使用有效的JSON,则必须自行设置格式并自行解析。
火箭Hazmat 2012年

Answers:


181

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

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

请注意,当您eval使用对象文字时,必须将其括在圆括号中,否则将花括号解析为块而不是对象。

我也同意以下问题的评论:最好以有效的JSON开始编码对象,而不必先解析,编码,然后大概再次解析它,这会更好。HTML支持单引号属性(只需确保对字符串内的任何单引号进行HTML编码)。


如果字符串来自受信任的源,这没有任何意义,为什么我们将其转换为有效的json呢?
allenhwkim 2014年

2
@allenhwkim这个想法是将无效的JSON转换为有效的JSON,因此eval将字符串转换为JavaScript对象(只要字符串代表有效的JavaScript,即使它不是有效的JSON,该对象也可以使用)。然后JSON.stringify从一个对象转换回一个(有效的)JSON字符串。eval如果该字符串不是来自受信任的来源,则调用是危险的,因为该字符串实际上可以运行任何JavaScript,从而可能引发跨站点脚本攻击。
马修·克鲁姆利

2
例如,如果构造字符串,eval在这种情况下仍然会做坏事情:var str =“(function(){console.log(\” bad \“)})()”;
龙多

使用eval()将执行JS代码。它很容易被滥用。
FisNaN

@allenhwkim:我们从不信任任何来源。信任IT意味着检查,检查并再次检查。
拉斯洛·瓦尔加

110

您的字符串不是有效的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生成,应该在生成之前固定在那里,而不是之后。

编辑:您说过(在注释中)此字符串存储在data属性中:

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


43

在下面的链接中使用简单的代码:

http://msdn.microsoft.com/es-es/library/ie/cc836466%28v=vs.94%29.aspx

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

和反向

var str = JSON.stringify(arr);

为了类型安全,通过新的String(jsontext)将jsontext转换为String对象可能更好。
模糊分析

@fuzzyanalysis:不,永远不要使用原始包装器。
Ry-

1
如@LouiseMcMahon所述,这里应该接受JSON.parse()的答案
pixel

24

我希望这个小功能可以将无效的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+'"'})         
}

结果

var 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取消评估b.parse我们的代码,这看起来是一个很好的解决方案。我们仍然需要手动处理常量替换,但这至少可以容纳这些情况。
拉韦米尔

1
几乎完美。: 在其中一个值中时不起作用。
seler '18

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 2012年

1
@Rocket:你错了。a)eval()是唯一的方法。b)我警告操作员。c)看一下Matthew Crumley的回答,并想出一个更好的解释。(哦,和d)eval()以这种广义形式讲的陈述不好是胡说八道。)
Tomalak

2
@Rocket:啊,误会就在那里。对不起,我以为那票是你的。:)
Tomalak

1
@kuboslav:它工作正常,您是否进行了测试?他这样做eval("var x = " + str + ";")是完全有效的JS。你不需要做var x = ({a:12})
火箭Hazmat 2012年

2
@kuboslav在IE7中不起作用,因为IE7没有本机JSON支持。使用后,它将立即开始工作json2.js。别那么高兴。
Tomalak 2012年

4

免责声明:请勿在家中尝试此操作,或需要其他开发人员认真对待的任何操作:

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

在那里,我做到了。
尽量不要这样做,因为评估对您来说很不好。如上所述,对于较旧的浏览器(IE7及更低版本)使用Crockford的JSON填充程序

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

编辑:固定火箭建议。


它应该是 JSON.stringify(eval('('+str+')'));,不是我宽容的eval,但是他的字符串不是有效的JSON,因此JSON.parse不起作用。
火箭Hazmat 2012年

4

我的答案是对这个旧主题感兴趣的人。

我为jQuery插件和演示创建了HTML5 data- *解析器,该解析器无需使用即可将格式错误的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"
}


2

有一种更简单的方法可以完成此任务,只需劫持虚拟元素的onclick属性即可强制将字符串作为JavaScript对象返回:

var jsonify = (function(div){
  return function(json){
    div.setAttribute('onclick', 'this.__json__ = ' + json);
    div.click();
    return div.__json__;
  }
})(document.createElement('div'));

// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)

这是一个演示: http : //codepen.io/csuwldcat/pen/dfzsu(打开控制台)


2

您需要使用“ 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);

在此处输入图片说明


1

您必须编写圆括号,因为如果没有它们,它们eval会将大括号内的代码视为命令块。

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

1

最好和最安全的选择是JSON5-JSON for Humans。它是专门为该用例创建的。

const result = JSON5.parse("{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }");

console.log(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/0.5.1/json5.min.js"></script>


1

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


0

对于上面的简单示例,您可以使用2个简单的正则表达式替换来实现:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
 => '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

大警告:这种幼稚的方法假定对象没有包含':字符的字符串。例如,如果不使用以下方法,我想不出一种将以下对象字符串转换为JSON的好方法eval

"{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"

0

只是出于怪癖,您可以通过以下方式转换您的字符串 babel-standalone

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

function toJSON() {
  return {
    visitor: {
      Identifier(path) {
        path.node.name = '"' + path.node.name + '"'
      },
      StringLiteral(path) {
        delete path.node.extra
      }
    }
  }
}
Babel.registerPlugin('toJSON', toJSON);
var parsed = Babel.transform('(' + str + ')', {
  plugins: ['toJSON']
});
var json = parsed.code.slice(1, -2)
console.log(JSON.parse(json))
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>


0

var str =“ {hello:'world',place:['Africa','America','Asia','Australia']}” var fStr = str .replace(/([[Az] *)(:)/ g,'“ $ 1”:').replace(/'/ g,“ \”“)

console.log(JSON.parse(fStr))在此处输入图片说明

抱歉,我在电话上,这是一张照片。


0

使用一个正则表达式而不使用eval的解决方案:

str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")

我相信这应该适用于多行,并且所有可能出现的单引号'string'都被双引号“ string”替换(/ g标志)。


0
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

-1

也许您必须尝试以下方法:

str = jQuery.parseJSON(str)

问题指定为“或jQuery”,如果可用,这是一个完美的解决方案。
Ecropolis
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.