【问题标题】:javascript regex replace all doublequotes in string unless the doublequote is followed by space or comma spacejavascript 正则表达式替换字符串中的所有双引号,除非双引号后跟空格或逗号空格
【发布时间】:2013-06-20 18:33:29
【问题描述】:

我有一个问题,有人没有正确地转义值中的双引号,以便稍后将其解释为 JSON 字符串。

字符串示例:

{"description":"This is my 12" pizza I ordered.","value":"1"}

当我尝试让 JSON.parse() 处理它时,由于未转义的双引号(指以英寸为单位的大小)而导致错误

起初,我想 - 就这样吧:

string.replace(/\"/g,'\"');

但当然,这也会转义所有有效的双引号。所以,我不是正则表达式方面的专家,但我环顾四周寻找一些答案,我认为这需要消极的前瞻性?

有人可以帮助构建一个正则表达式来查找(替换)任何双引号序列,其中有问题的双引号后面的下一个 2 字符序列不是空格逗号吗?

我知道这不是一个完全通用的解决方案,(让这个人自己解决),但不幸的是我没有通用解决方案的奢侈。

TIA

更新 - 而不是考虑示例字符串(仅用于说明)。是否可以在每个双引号之前和之后测试是否存在有效的 JSON - 即查找以下任何字符 ,{[:

在每个双引号之前和之后?我想这就是我要问的 - 这可以通过前瞻/后置正则表达式来完成吗?

【问题讨论】:

  • 最好在创建时完成;你是如何创建你的 JSON 的?
  • 当你使用 JSON.stringify 把你的“东西”变成一个 json 对象时,它应该为你做自动转义。你不应该自己做这个;你能展示一下你是如何构建你要转换为 JSON 的对象的吗?
  • 您要求的正则表达式无法解决您的问题,因为不应转义单词“description”、“this”和“value”前面的双引号,但是后不紧跟逗号或空格字符。
  • 您将如何处理这种情况? {"description":"I'd like a 10", or maybe a 12", and make it "thin crust""} 很难做到这一点。纠正 JSON 不仅仅是“通用”修复,它是 only 修复。为什么他们要手动生成它而不是使用适当的 JSON 字符串化器?服务器代码是什么语言的?每种流行的服务器语言都有可用的 JSON 生成器。
  • 回答格式错误的 JSON 字符串的来源问题 - 我没有创建字符串,所以我无法修复它。我知道让 JSON 正确是唯一真正的解决方法,但如果这不可能,我正在寻找尽可能强大的替代方案。相信我 - 我不满意将糟糕的 JSON 作为唯一的解决方案!

标签: javascript regex json


【解决方案1】:

这是我能做的最好的事情,利用 JSON 中未转义的引号只能出现在某些地方这一事实。

input = '{"description":"This is my 12" pizza, and I want "thin crust"","value":"1"}';
console.log(input);
output = input.replace(/{"/g, '_OPEN_').replace(/":"/g, '_COLON_').replace(/","/g, '_COMMA_').replace(/"}/g, '_CLOSE_');
output = output.replace(/"/g, '\\"');
output = output.replace(/_OPEN_/g, '{"').replace(/_COLON_/g, '":"').replace(/_COMMA_/g, '","').replace(/_CLOSE_/g, '"}');
console.log(output)

生产

{"description":"This is my 12" pizza, and I want "thin crust"","value":"1"}
{"description":"This is my 12\" pizza, and I want \"thin crust\"","value":"1"}

您可以用输入中不太可能出现的字符串替换“OPEN”、“CLOSE”等,如果您不介意正则表达式晦涩难懂,甚至可以控制字符。但正如其他人所指出的,没有适用于所有情况的解决方案。无论您做什么,描述文本中都可能出现一个值,这会让您感到困惑,因为与正确生成的 JSON 不同,您尝试解析的语法是模棱两可的。

【讨论】:

    【解决方案2】:

    试试这个替换:

    repl = str.replace(/"(?= )/g, "\\\"");
    

    【讨论】:

      【解决方案3】:

      不是单行正则表达式,但我认为这样做更安全:

       json_string = '{"description":"This is my 12" pizza: which can also contain other "," which would break in a one liner regex.","value":"1"}';
       console.log(json_string);
      
       // save the value for later use
       var value = json_string.match(/"value":"(.+)"}$/)[1];
      
       // isolate just the description value..
      
       // remove the ","value... from the end
       var desc = json_string.replace(/","value":".+"}$/, '');
      
       // remove the opening {"description":" from the description value
       desc = desc.replace(/^{"description":"/, '');
      
       // any remaining " in the description are unwanted to replace them
       desc = desc.replace(/"/g, '"');
       console.log(desc);
      
       // now put it all back together - if you wanted too - but really you already have the description and value parsed out of the string
       json_string = '{"description":"'+desc+'","value":"'+value+'"}'
      
       console.log(json_string);
      

      控制台输出如下:

      {"description":"This is my 12" pizza: which can also contain other "," which would break in a one liner regex.","value":"1"}
      
      This is my 12" pizza: which can also contain other "," which would break in a one liner regex.
      
      {"description":"This is my 12" pizza: which can also contain other "," which would break in a one liner regex.","value":"1"}
      

      注意如果说描述还包含您可能在正则表达式单行中使用的任何模式,则此方法不会中断

      【讨论】:

        【解决方案4】:

        一种方法:重建json字符串:

        var str = '{"description":"This is my 12" pizza I ordered.","value":"1"}';
        var regex = /"(.*?)"(?=\s*([,:])\s*"|(}))/g;
        var result = '{';
        
        var arr = regex.exec(str);
        
        while (arr != null) {
            result += '"' + arr[1].replace(/\\?"/g, '\\"') + '"';
            if (arr[2]) result += arr[2];
            if (arr[3]) result += arr[3];
            arr = regex.exec(str);
        }
        
        console.log(result);
        

        【讨论】:

        • 如果您确定描述内容,这很好,因为值为:{"description":"This, "pizza","is my 12" Pizza", I ordered.","value ":"1"} 不适用于此解决方案,而在我上面的解决方案中却可以。
        【解决方案5】:

        我讨厌回答我自己的问题,正如你们中的许多人指出的那样,正确地在事后修复错误的 JSON 是不可能的,因为一个杂散的、未转义的双引号字符注入了歧义。可能这应该是一个正确的答案,不幸的是它不能解决我的问题。

        对于那些遇到同样问题的人 - 我希望下面的函数有助于创可贴,直到您可以修复错误 JSON 的来源。本质上,您必须查看每个双引号,然后(至少)向前和后面两个字符并根据前一个/下一个字符评估它是否可能在 JSON 中有效使用 doubleqoute 或无效。如果它无效,则拼接一个转义字符。下面的函数做得很好,但取决于由于双引号导致的 JSON 畸形程度,您可能需要稍微扩展此函数。我希望对于我这种情况的人来说,这至少提供了一个很好的起点。

        感谢所有贡献者 - 潜在解决方案的数量和广度非常值得回顾!

        // fix unescaped double quotes / malformed JSON
        function cleanseJSON(jsonStr)
        {
          for(var k=0;k<jsonStr.length;k++)
          { 
            if(jsonStr.charAt(k)=='"')
            {
              var prevChar=jsonStr.charAt(k-1);
              var prevChar2=jsonStr.charAt(k-2);
              var nextChar=jsonStr.charAt(k+1);
              var nextChar2=jsonStr.charAt(k+2);
              var esc="\\";
              var isValid=false;
              var prevFix=false;
              var postFix=false;
        
              switch(prevChar)
              {
                case ':':
                case '{':
                case ',':
                case '[':
                case '\\':   // already escaped
                  isValid=true;
                  break;
                default:
                  prevFix=true;
              }
        
              switch(nextChar)
              {
                case ':':
                case '}':
                case ',':
                  if(nextChar2==' '){   // if there is a comma, but the next is a space consider it invalid JSON
                    break;  
                  }
                case ']':
                case '\\':   // already escaped
                  isValid=true;
                  break;
                default:
                  postFix=true;
              }
              // first test to ensure the quote is likely bogus
              if(!isValid)
              {
                if(prevFix){
                  jsonStr = [jsonStr.slice(0, k), esc, jsonStr.slice(k)].join('');   
                } else {
                  if(postFix){
                    jsonStr = [jsonStr.slice(0, k+1), esc, jsonStr.slice(k+1)].join('');
                  }
                }
              } // if not valid "
            } // if we find a doublequote
          } // for each char in the jsonStr
          return jsonStr;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-24
          • 2012-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-10
          • 1970-01-01
          相关资源
          最近更新 更多