在没有 eval 的情况下解析“轻松”的 JSON

IT技术 javascript json
2021-01-20 10:42:03

解析“轻松”JSON 但避免邪恶的最简单方法是什么eval

以下抛出错误:

JSON.parse("{muh: 2}");

因为正确的 JSON 应该有引用的键: {"muh": 2}


我的用例是一个简单的测试接口,用于将 JSON 命令写入我的节点服务器。到目前为止,我只是简单地使用eval它,因为它只是一个测试应用程序。然而,在整个项目中使用 JSHint 一直困扰着我eval所以我想要一个安全的替代方案,它仍然允许对键使用宽松的语法。

PS:我不想仅仅为了测试应用程序而自己编写解析器:-)

6个回答

您可以使用正则表达式替换来清理 JSON:

var badJson = "{muh: 2}";
var correctJson = badJson.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": ');
JSON.parse(correctJson);
如果您有一个包含日期的字符串,这将不起作用。(15/2/2017 17:00:00)
2021-03-12 10:42:03
不适用于包含:(URL、引文等)但仍为我节省了一些工作的任何字符串
2021-03-15 10:42:03
刚刚意识到这个正则表达式对于包含冒号的值失败,例如 {muh: "2:30pm"}
2021-03-22 10:42:03
这个正则表达式有效,@kennebec 的那个不适用于value包含布尔值的JSON
2021-04-04 10:42:03
如果您在此\s*之前添加:/g您还可以修复冒号前有空格的 JSON 字符串,例如{muh : 2}
2021-04-04 10:42:03

你已经知道这一点,因为你在这里提到了我,但我认为在这里记录它可能会很好:

长期以来,我一直希望能够编写仍然有效的 JS 的“轻松”JSON,因此我采用了 Douglas Crockford 的 eval-free json_parse.js并将其扩展为支持 ES5 功能:

https://github.com/aseemk/json5

该module在 npm 上可用,可用作本地JSON.parse()方法的直接替代品(它stringify()输出常规的 JSON。)

希望这可以帮助!

由于“生命周期结束”的原因,文件在提交中被删除。从提交历史链接到文件:github.com/douglascrockford/JSON-js/blob/...
2021-03-27 10:42:03

这就是我最终不得不做的事情。我扩展了@ArnaudWeil 的回答,并添加了对:出现在值中的支持:

var badJSON = '{one : "1:1", two : { three: \'3:3\' }}';

var fixedJSON = badJSON

	// Replace ":" with "@colon@" if it's between double-quotes
	.replace(/:\s*"([^"]*)"/g, function(match, p1) {
		return ': "' + p1.replace(/:/g, '@colon@') + '"';
	})

	// Replace ":" with "@colon@" if it's between single-quotes
	.replace(/:\s*'([^']*)'/g, function(match, p1) {
		return ': "' + p1.replace(/:/g, '@colon@') + '"';
	})

	// Add double-quotes around any tokens before the remaining ":"
	.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?\s*:/g, '"$2": ')

	// Turn "@colon@" back into ":"
	.replace(/@colon@/g, ':')
;

console.log('Before: ' + badJSON);
console.log('After: ' + fixedJSON);
console.log(JSON.parse(fixedJSON));

它产生这个输出:

Before: {one : "1:1", two : { three: '3:3' }}
After: {"one":  "1:1", "two":  { "three":  "3:3" }}
{
  "one": "1:1",
  "two": {
    "three": "3:3"
  }
}
@torazaburo:当然,但也许当发生这种情况时,有人可以在此基础上进行构建以解决问题,就像我建立在较早的解决方案上来解决我发现的问题一样。
2021-03-18 10:42:03
一种奇怪的编码方法 - 编写您知道可能会损坏的代码,并计划稍后修复它。
2021-03-19 10:42:03
这对我有用,但是如果我们能对每一行的作用发表一些评论,那就太好了。只是为了我们不是正则表达式专家的道德。
2021-03-26 10:42:03
@torazaburo:你可能认为它会崩溃,但我正在处理一个不会改变的遗留系统,所以它对我来说不会比任何其他代码更容易崩溃。如果您认为这个答案很糟糕,为什么不贡献一个更好的答案呢?我想看看你打算如何以一种不会在未来的边缘情况下中断的方式来解决这个问题。
2021-04-03 10:42:03
这几乎可以保证在未来的某些边缘情况下会中断。
2021-04-05 10:42:03

JSON5看起来得到了很好的支持,但这个轻松的 json库看起来也是一个不错的选择。

github.com/phadej/relaxed-json 上的轻松 json 正是我需要的 TY
2021-03-18 10:42:03

如果在写字符串的时候不能引用keys,可以在使用JSON.parse-之前插入引号

var s= "{muh: 2,mah:3,moh:4}";
s= s.replace(/([a-z][^:]*)(?=\s*:)/g, '"$1"');

var o= JSON.parse(s);
/*  returned value:[object Object] */
JSON.stringify(o)
/*  returned value: (String){
    "muh":2, "mah":3, "moh":4
}
> '{muh: "foo",mah:3,moh:4}'.replace(/([az][^:]*)(?=\s*:)/g, '"$1"'); '{"muh": ""foo",mah":3,"moh":4}' 我正在考虑这个,但看例子它并没有完全削减它。它有点复杂。
2021-03-20 10:42:03
尝试将引号插入到无效的 JSON 中,如下所示:"{muh: true, notMuch: 123, pika:{pika:\"chu\"}}"结果将是{"muh": "true, notMuch": 123, "pika":{"pika":"chu"}}
2021-03-24 10:42:03
谢谢你真的回答了这个问题!
2021-03-25 10:42:03
您忘记在 RegExp 中包含 /i 修饰符,如下所示: s= s.replace(/([a-z][^:]*)(?=\s*:)/gi, '"$1"');
2021-03-27 10:42:03