将对象字符串转换为 JSON
Posted
技术标签:
【中文标题】将对象字符串转换为 JSON【英文标题】:Convert object string to JSON 【发布时间】:2012-02-20 15:03:16 【问题描述】:如何使用 javascript(或 jQuery)将描述对象的字符串转换为 JSON 字符串?
例如:转换这个(不是一个有效的 JSON 字符串):
var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] "
进入这个:
str = ' "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] '
如果可能,我希望避免使用eval()
。
【问题讨论】:
为什么你的字符串首先不是有效的 JSON?你是怎么产生的? 字符串存储在data
-attrubute 中,如下所示:<div data-object="hello:'world'"></div>
我不想在 html 中使用单引号(因此它可能不可信)
@snorpey: <div data-object='"hello":"world"'></div>
是 100% 有效的 HTML(单引号与信任与否有什么关系?)。如果你这样做,你可以JSON.parse
它,它会正常工作。 注意:键也需要引用。
@Rocket 感谢您的努力!我只是想找到一种方法来避免在 HTML 中使用单引号(即使它是 100% 有效)和 JSON 表示法。
@snorpey:他们的方法是首先不将 JSON 放在 HTML 属性中。我猜你可以使用双引号,并转义 JSON <div data-object="\"hello\":\"world\""></div>
中的双引号。如果您不想在属性中使用有效的 JSON,那么您将不得不制作自己的格式并自己解析。
【参考方案1】:
这也可以
let str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] "
let json = JSON.stringify(eval("("+ str +")"));
【讨论】:
【参考方案2】:我希望这个小函数可以将无效的 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 进行反评估,这看起来是一个不错的解决方案。我们仍然需要手动处理不断的替换,但至少这允许包含这些情况。 几乎完美。当:
处于其中一个值时不起作用。
eval 是纯粹的邪恶,我认为这是要走的路
绝对的天才【参考方案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
来源: MDN, 2ality
【讨论】:
【参考方案4】:var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] ";
var json = JSON.stringify(eval("(" + str + ")"));
【讨论】:
【参考方案5】:您最好和最安全的选择是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>
【讨论】:
【参考方案6】:您需要使用“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);
【讨论】:
【参考方案7】:也许你必须试试这个:
str = jQuery.parseJSON(str)
【讨论】:
问题指定为“或 jQuery”,如果你有它,这是完美的解决方案。【参考方案8】:使用一个正则表达式而不使用 eval 的解决方案:
str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")
我相信这应该适用于多行和所有可能出现的单引号“字符串”(/g 标志)替换为双引号“字符串”。
【讨论】:
【参考方案9】:var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] " var fStr = str .replace(/([A-z]*)(:)/g, '"$1":') .replace(/'/g, "\"")
console.log(JSON.parse(fStr))
对不起,我在用手机,这是一张照片。
【讨论】:
【参考方案10】:只是为了它的怪癖,你可以通过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>
【讨论】:
【参考方案11】:对于上面的简单示例,您可以使用 2 个简单的正则表达式替换来做到这一点:
var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] ";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
=> ' "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] '
大警告:这种天真的方法假定对象没有包含'
或:
字符的字符串。例如,我想不出不使用eval
将以下对象字符串转换为 JSON 的好方法:
" hello: 'world', places: [\"America: The Progressive's Nightmare\"] "
【讨论】:
【参考方案12】:使用下面链接中的简单代码:
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);
【讨论】:
为了类型安全,通过 new String(jsontext) 将 jsontext 转换为 String 对象可能会更好。 @fuzzyanalysis:不,不应该使用原始包装器。 JSON.parse() 应该是@LouiseMcMahon 所述的可接受的答案【参考方案13】:有一个更简单的方法来完成这个壮举,只需劫持一个虚拟元素的 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(打开你的控制台)
【讨论】:
【参考方案14】:我把我的答案献给对这个旧线程感兴趣的人。
我为 jQuery 插件创建了 HTML5 data-* parser 和 demo,它们在不使用 eval()
的情况下将格式错误的 JSON 字符串转换为 JavaScript 对象。
它可以传递HTML5 data-* 属性如下:
<div data-object='"hello":"world"'></div>
<div data-object="hello:'world'"></div>
<div data-object="hello:world"></div>
进入对象:
hello: "world"
【讨论】:
【参考方案15】:谨慎使用(因为eval()
):
function strToJson(str)
eval("var x = " + str + ";");
return JSON.stringify(x);
调用为:
var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] ";
alert( strToJson(str) );
【讨论】:
致匿名的反对者。我挑战你提供更好的解决方案。除此之外,否决票的理由会很好。 @Rocket:你错了。 a)eval()
是唯一的方法。 b)我警告过OP。 c) 查看 Matthew Crumley 的回答并想出一个更好的解释。 (哦,还有 d)声明 eval()
is bad 在这种广义形式中是无稽之谈。)
@Rocket:啊,误会了。抱歉,我以为反对票是你的。 :)
@kuboslav:它工作正常,你测试过吗?他正在做eval("var x = " + str + ";")
,这是完全有效的 JS。你不需要做var x = (a:12)
。
@kuboslav 它在 IE7 中不起作用,因为 IE7 没有原生 JSON 支持。只要您使用json2.js
,它就会开始工作。不要那么高兴。【参考方案16】:
如果字符串来自受信任的来源,您可以使用eval
然后JSON.stringify
结果。像这样:
var str = " hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] ";
var json = JSON.stringify(eval("(" + str + ")"));
请注意,当您eval
一个对象字面量时,它必须用括号括起来,否则大括号将被解析为块而不是对象。
我也同意 cmets 提出的问题,即最好只用有效的 JSON 编码对象,然后避免解析、编码,然后大概再解析它再次。 HTML 支持单引号属性(只需确保对字符串中的任何单引号进行 HTML 编码)。
【讨论】:
这没有意义,如果字符串来自受信任的来源,为什么我们将其转换为有效的 json。 @allenhwkim 想法是将无效的 JSON 转换为有效的 JSON,因此eval
将字符串转换为 JavaScript 对象(只要字符串表示有效的 JavaScript,即使它不是有效的 JSON)。然后JSON.stringify
从一个对象转换回一个(有效的)JSON 字符串。如果字符串不是来自受信任的来源,则调用 eval
是危险的,因为它实际上可以运行任何 JavaScript,这会打开跨站点脚本攻击的可能性。
在这种情况下,如果构造字符串,eval 仍然会做坏事,例如,像这样: var str = "(function() console.log(\"bad\")) ()";
使用 eval() 将执行 JS 代码。它很容易被滥用。
@allenhwkim:我们从不信任任何来源。对 IT 的信任意味着检查、检查和再检查。【参考方案17】:
您的字符串不是有效的 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
是如何生成的,应该在生成之前修复,而不是生成之后。
编辑:您说(在 cmets 中)此字符串存储在数据属性中:
<div data-object="hello:'world'"></div>
我建议你在这里修复它,所以它可以是JSON.parse
d。首先,它们的键和值都需要用双引号引起来。它应该看起来像(HTML 中的单引号属性有效):
<div data-object='"hello":"world"'></div>
现在,您可以使用 JSON.parse
(或 jQuery 的 $.parseJSON
)。
var str = '"hello":"world"';
var obj = JSON.parse(str);
【讨论】:
【参考方案18】:您必须编写圆括号,因为没有它们eval
会将大括号内的代码视为命令块。
var i = eval("( hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] )");
【讨论】:
【参考方案19】:免责声明:不要在家里尝试这个,或者任何需要其他开发者认真对待的事情:
JSON.stringify(eval('(' + str + ')'));
在那里,我做到了。 尽量不要这样做, eval 对你不利。如上所述,为旧版浏览器(IE7 及以下)使用 Crockford 的 JSON shim
此方法要求您的字符串是有效的javascript,它将被转换为一个 javascript 对象,然后可以序列化为 JSON。
编辑: 按照 Rocket 的建议修复。
【讨论】:
应该是JSON.stringify(eval('('+str+')'));
,不是我宽恕eval
,而是他的字符串不是有效的JSON,所以JSON.parse
不起作用。【参考方案20】:
jQuery.parseJSON
str = jQuery.parseJSON(str)
编辑。前提是您有一个有效的 JSON 字符串
【讨论】:
true 我看到的问题是如何将 JSON 字符串转换为对象【参考方案21】:Douglas Crockford 有一个转换器,但我不确定它是否有助于将坏 JSON 转换为好 JSON。
https://github.com/douglascrockford/JSON-js
【讨论】:
这并没有真正的帮助,因为字符串不是有效的 JSON。以上是关于将对象字符串转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章