我试图在 Javascript 中使用正则表达式来解决同样的问题。我有一个为 Node.js 编写的应用程序来解析传入的 JSON,但想要一个“宽松”版本的解析器(请参阅下面的评论),因为在每个键(名称)周围加上引号是不方便的。这是我的解决方案:
var objKeysRegex = /({|,)(?:\s*)(?:')?([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)(?:')?(?:\s*):/g;// look for object names
var newQuotedKeysString = originalString.replace(objKeysRegex, "$1\"$2\":");// all object names should be double quoted
var newObject = JSON.parse(newQuotedKeysString);
以下是正则表达式的细分:
({|,)
查找对象的开头,a{
查找平面对象或,
嵌入对象。
(?:\s*)
找到但不记得空白
(?:')?
找到但不记得单引号(稍后将替换为双引号)。将有零个或其中之一。
([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)
是名称(或键)。以任何字母、下划线、$ 或点开头,后跟零个或多个字母数字字符或下划线或破折号或点或 $。
- 最后一个字符
:
将对象的名称与值分隔开来。
现在我们可以使用replace()
一些修饰来获取我们新引用的键:
originalString.replace(objKeysRegex, "$1\"$2\":")
其中$1
是{
或者,
取决于对象是否嵌入到另一个对象中。 \"
添加双引号。 $2
是名字。\"
另一个双引号。最后:
完成它。测试一下
{keyOne: "value1", $keyTwo: "value 2", key-3:{key4:18.34}}
输出:
{"keyOne": "value1","$keyTwo": "value 2","key-3":{"key4":18.34}}
一些评论:
- 我没有测试过这种方法的速度,但是从我通过阅读其中一些条目收集到的信息是,使用正则表达式比
eval()
- 对于我的应用程序,我限制了
([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)
我的“宽松”版本 JSON 解析器允许名称使用的字符。如果您想在名称中允许更多字符(您可以这样做并且仍然有效),您可以改为使用([^'":]+)
双引号或单引号或冒号以外的任何字符。你可以用这个表达式在这里有各种各样的东西,所以要小心。
- 一个缺点是这种方法实际上改变了原始传入的数据(但我认为这就是你想要的?)。您可以围绕它进行编程以缓解此问题 - 取决于您的需求和可用资源。
希望这可以帮助。——约翰·L。