在没有评估的情况下解析"放松"的JSON

axk*_*ibe 40 javascript json

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

以下引发错误:

JSON.parse("{muh: 2}");
Run Code Online (Sandbox Code Playgroud)

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


我的用例是一个简单的测试接口,用于将JSON命令写入节点服务器.到目前为止,我只是使用eval它,因为它只是一个测试应用程序.但是,在整个项目中使用JSHint总是让我烦恼不已eval.所以我想要一个安全的选择,仍然允许放宽键的语法.

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

Ase*_*ore 21

你已经知道了,因为你在这里引用我 = D,但我认为在这里记录它可能是好的:

我一直渴望能够编写仍然有效JS的"轻松"JSON,所以我采用了Douglas Crockford的无eval json_parse.js并扩展它以支持ES5功能:

https://github.com/aseemk/json5

此模块在npm上可用,可用作本机JSON.parse()方法的替代品.(它stringify()输出常规JSON.)

希望这可以帮助!=)


Arn*_*eil 20

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

var badJson = "{muh: 2}";
var correctJson = badJson.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": ');
JSON.parse(correctJson);
Run Code Online (Sandbox Code Playgroud)

  • 刚刚意识到这个正则表达式失败了包含冒号的值,例如`{muh:"2:30 pm"}` (3认同)
  • 这个正则表达式工作,@kennebec的那个不适用于包含布尔值的JSON`value` (2认同)
  • 如果在`:/ g`之前添加`\ s*`,那么你也可以修复在冒号之前有空格的JSON字符串,比如`{muh:2}` (2认同)
  • 不适用于包含`:`(URL,引用,...)的任何字符串,但仍然为我节省了一些工作. (2认同)

Mal*_*ous 10

这就是我最终要做的事情.我扩展了@ 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));
Run Code Online (Sandbox Code Playgroud)

它产生这个输出:

Before: {one : "1:1", two : { three: '3:3' }}
After: {"one":  "1:1", "two":  { "three":  "3:3" }}
{
  "one": "1:1",
  "two": {
    "three": "3:3"
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @torazaburo:你可能会认为它会破坏,但我正在处理一个不会改变的遗留系统,所以它不会比任何其他代码更容易破坏我.如果你认为这个答案是如此糟糕,为什么不做出更好的答案呢?我想看看你是如何建议以一种不会破坏未来边缘情况的方式来解决这个问题. (4认同)
  • 这几乎可以保证在未来的某些边缘情况下会中断。 (2认同)
  • @torazaburo:当然,但也许当这种情况发生时,有人可以在它的基础上构建来解决问题,就像我在早期的解决方案上构建来解决我发现的问题一样。 (2认同)

And*_*Mao 8

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


ken*_*bec 7

如果在编写字符串时无法引用键,则可以在使用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
}
Run Code Online (Sandbox Code Playgroud)