繁体   English   中英

在JavaScript中解析格式错误的JSON

[英]Parsing malformed JSON in JavaScript

谢谢你的期待!

背景

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

{foo: "bar"}

我无法控制服务,所以我这样纠正:

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

这给了我很好的JSON:

{“foo”:“bar”}

问题

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

UPDATE

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

您可以完全避免使用正则表达式,并仍然使用这个简单的技巧从错误的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 (打开你的控制台)

这样的事情可能有助于修复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')

有一个项目可以处理JSON中的各种无效案例https://github.com/freethenation/durable-json-lint

我试图在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.

怎么样?

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

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

    return output;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM