在JavaScript中解析格式错误的JSON

时间:2013-08-16 18:56:26

标签: javascript regex json parsing

感谢您的期待!

背景

我正在编写一些使用JSON服务的前端代码,该服务返回格式错误的JSON。具体来说,键不包含引号:

{foo: "bar"}

我对服务没有控制权,所以我这样纠正:

var scrubbedJson = dirtyJson.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');

这给了我很好的JSON:

{“foo”:“bar”}

问题

但是,当我拨打JSON.parse(scrubbedJson)时,我仍然会收到错误消息。我怀疑这可能是因为整个JSON字符串被双引号包围但我不确定。

更新

这已经解决了 - 上面的代码工作正常。我在返回的JSON正文中有一个流氓单引号。我把它从那里拿出来,现在一切都解析了。谢谢。 任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:3)

您可以完全避免使用正则表达式,并且仍然使用这个简单的技巧从错误的JSON字符串(没有引号,单引号等的键)输出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(打开你的控制台)

答案 1 :(得分:2)

这样的事情可能有助于修复json ..

$str='{foo:"bar"}';
echo preg_replace('/({)([a-zA-Z0-9]+)(:)/','$1"$2"${3}',$str);

输出:

{"foo":"bar"}

编辑:

var str='{foo:"bar"}';
str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')

答案 2 :(得分:0)

有一个项目负责处理JSON https://github.com/freethenation/durable-json-lint

中的各种无效案例

答案 3 :(得分:0)

我试图在Javascript中使用regEx来解决同样的问题。我有一个为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);

以下是regEx的细分:

  • ({|,)查找对象的开头,平面对象为{,嵌入对象为,
  • (?:\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解析器的字符。如果你想在名称中允许更多的字符(你可以这样做并且仍然有效),你可以使用([^'":]+)表示除双引号或单引号或冒号之外的任何字符。你可以用这个表达式在这里有各种各样的东西,所以要小心。
  • 一个缺点是这种方法实际上改变了原始传入数据(但我认为这是你想要的?)。您可以对此进行编程以缓解此问题 - 取决于您的需求和可用资源。

希望这会有所帮助。 -John L。

答案 4 :(得分:-1)

怎么样?

function fixJson(json) {
    var tempString, tempJson, output;

    tempString = JSON.stringify(json);
    tempJson = JSON.parse(tempString);
    output = JSON.stringify(tempJson);

    return output;
}