【问题标题】:Regular Expression to add double quotes around keys in JavaScript正则表达式在 JavaScript 中的键周围添加双引号
【发布时间】:2011-06-18 03:25:12
【问题描述】:

我正在使用 jQuery 的 getJSON 函数发出请求并处理 JSON 响应。问题是我得到的响应格式不正确,我无法更改它。响应如下所示:

{
    aNumber: 200,    
    someText: '\'hello\' world',
    anObject: {
        'foo': 'fooValue',
        'bar': '10.0'
    } 
}

要成为有效的 JSON,它应该如下所示:

{
    "aNumber": 200,    
    "someText": "'hello' world",
    "anObject": {
        "foo": "fooValue",
        "bar": "10.0"
    } 
}

我想将返回的文本更改为有效的 JSON 对象。我已经使用 JavaScript 替换函数将单引号转换为双引号,并将转义的单引号转换为单引号,但现在我一直在寻找在键值周围添加引号的最佳方法。

例如,如何将foo: "fooValue" 更改为"foo":"fooValue"?有没有正则表达式可以让这变得简单?

提前致谢!

【问题讨论】:

  • 我在another question写了一个转换函数,用的是简单的正则表达式,不需要eval()

标签: javascript regex json


【解决方案1】:

edit — 回过头来首先指出,这不是一个可以用正则表达式解决的问题。

区分作为序列化形式的 JSON 表示法和 JavaScript 对象常量表示法很重要。

这个:

{ x: "hello" }

是一个完全有效的 JavaScript 值(一个表达式片段),因此:

var y = { x: "hello" };

为您提供与以下内容完全相同的结果:

var y = { "x": "hello" };

换句话说,在这两种情况下,“y”的值将完全相同。完全一样,完全一样,因此永远无法分辨出这两个常量中的哪一个用于初始化“y”。

现在,如果您想要将包含 JavaScript 样式“JSON 速记”且不带引号的 字符串 转换为有效的 JSON,唯一要做的就是解析它并用引号重构字符串属性名称。也就是说,您将不得不编写自己的“宽松” JSON 解析器来处理不带引号的标识符作为属性名称,或者找到可以处理这种宽松语法的现成解析器。

在你的情况下,看起来一旦你有了“宽松”的解析器,你就完成了;应该不需要你翻译回来。值得庆幸的是,您的“无效” JSON 响应完全可以由 JavaScript 本身解释,因此如果您信任数据源(这是一个 big “如果”),您应该能够使用“eval()”对其进行评估”。

【讨论】:

    【解决方案2】:

    UPD 2020:您拥有的对象是有效的 javascript 对象,但不是 100% 有效的 JSON

    将其转换为有效 JSON 的一种简单方法是利用 JavaScript 为您提供的功能,JSON.stringify

    JSON.stringify(object)
    

    您可以在浏览器的 JS 控制台中运行它。

    要对其进行格式化(又称“漂亮打印”),您可以将两个参数传递给此函数 - replacer(该函数允许您过滤掉对象的某些属性; 如果你不关心,只需传递一个 nullspacenumber 个空格或将放置的 string在对象的字符串表示的每个键值对之前):

    JSON.stringify(object, null, 4)
    

    在你的情况下,这个电话

    JSON.stringify({
        aNumber: 200,    
        someText: '\'hello\' world',
        anObject: {
            'foo': 'fooValue',
            'bar': '10.0'
        } 
    }, null, 4)
    

    会给你

    {
        "aNumber": 200,
        "someText": "'hello' world",
        "anObject": {
            "foo": "fooValue",
            "bar": "10.0"
        }
    }
    
    您**不需要** 需要这样做 - 您已经拥有一个有效的 **JSON 对象**。阅读关于 JSON [这里][1]。 如果您需要获得价值,您只需编写 `data.whatever` 就可以了。例如:如果你有 JSON **object** `data`: { 哞:“富”, 富:“酒吧” } 所有可能的字段都是“moo”和“foo”,它们的用途分别是“data.moo”和“data.foo”。如果你想使用 `data` 作为 jQuery 参数,你只需按原样传递它:`$.load("http://my.site.com/moo", data, function(response){/* ... */ })`。 **注意:** 在我提到的最后一个示例中,响应将是一个字符串。要使其成为有效的 JSON 对象,请使用 `$.parseJSON(response);` 方法。

    【讨论】:

    • 他已经从他的服务器获得了一个响应字符串。问题是该字符串是 not 有效的 JSON。但是,它是有效的 JavaScript。
    • @Pointy,这里有一些演示:jsfiddle.net/kBZu5。请告诉我我哪里错了。还是我误解了问题?
    • 在真正的 JSON 表示法中,属性名称 - 冒号左侧的标识符 - 必须 被引用。所有引用都必须使用双引号字符 ("),而不是单引号字符。有关详细信息,请参阅 json.org。它是 JavaScript 对象文字语法的 子集
    • 这是一个有用的答案。虽然我在技术上没有有效的 JSON 对象,但我确实有有效的 Javascript。我将无法使用 jQuery 的 parseJSON,因为 parseJSON 需要格式正确的 JSON。但是,我可以通过 eval 函数运行响应以使用 data.moo 或 data.foo。
    • @Evil E,好吧,我很高兴它帮助了你! =)
    【解决方案3】:

    由于它是格式错误的“JSON”,您将无法使用 jQuery.getJSON。

    你可以使用

    jQuery.ajax({
          url : myUrl,
          data : myParams,
          type : "GET",
          success : function(jsontext)
          {
              // jsontext is in text format
              jsontext = jsontext.replace("'", "\"");
              // now convert text to JSON object
              var jsonData = eval('(' + jsontext+ ')');
    
              // rest of the code
          }
     });
    

    【讨论】:

    • 虽然,使用“eval”块可能容易受到攻击,并且可能会出现安全问题。您可以很好地使用 JSON 解析器作为 ---- JSON.parse(jsontext) 来获取 JSON 对象而不是 eval
    • 问题在于原始文本不是有效的 JSON。
    • 这是一个很棒的工作解决方案,非常接近我在阅读@Pointy 的答案后实施的解决方案。我使用了 jQuery.ajax 函数,但将 dataType 明确定义为“文本”。也不需要替换引号。
    【解决方案4】:

    我试图在 Javascript 中使用正则表达式来解决同样的问题。我有一个为 Node.js 编写的应用程序来解析传入的 JSON,但想要一个“宽松”版本的解析器(参见下面的 cmets),因为在每个键(名称)周围加上引号是不方便的。这是我的解决方案:

    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);
    

    以下是正则表达式的细分:

    • ({|,) 查找对象的开头,{ 查找平面对象或 , 查找嵌入对象。
    • (?:\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}}
    

    一些cmets:

    • 我没有测试过这种方法的速度,但是从我通过阅读其中一些条目收集到的信息是,使用正则表达式比eval() 更快
    • 对于我的应用程序,我在“宽松”版本的 JSON 解析器中限制了名称允许使用 ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) 的字符。如果您想在名称中允许更多字符(您可以这样做并且仍然具有有效的 JSON),则可以改用 ([^'":]+) 来表示除双引号或单引号或冒号之外的任何字符。这仍然会比 JSON 标准(允许名称中包含单引号)进一步限制您,但是您将无法使用此方法进行解析。用这个表达式([^'":]+),你可以在这里拥有各种各样的东西,所以要小心。

    希望这会有所帮助。

    【讨论】:

    • 对于许多情况来说,这是一个“足够好”的解决方案。但是请不要自欺欺人地认为任何正则表达式都可以处理所有输入。例如,考虑当这个正则表达式被输入这个输入时会发生什么:{"sillyValue" : "{hey:there}"}
    • 而且它还留下尾随空格 { name : "value"} => { "name_": "value" }
    【解决方案5】:

    这个正则表达式可以解决问题

    $json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);
    

    虽然它是一个 php!我认为将其转换为 JS 不是问题。

    【讨论】:

    • 完美!给我的 JS 朋友们JSON.parse(dirtyJSON.replace(/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/g, '$1"$3":'))
    猜你喜欢
    • 2017-11-17
    • 2017-01-30
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    相关资源
    最近更新 更多