javascript正则表达式替换字符串中的所有双引号,除非双引号后跟空格或逗号空格

时间:2013-06-20 18:33:29

标签: javascript regex json

我遇到一个问题,即有人在以后没有正确地转义值中的双引号被解释为JSON字符串。

字符串示例:

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

当我尝试让JSON.parse()处理它时,由于未转义的双引号(参考以英寸为单位的大小),它会产生错误

起初,我想 - 只是这样做:

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

但当然这也逃脱了所有有效的双引号。所以,我不是正则表达式的专家,但我四处寻找答案,我认为这需要一个负面的预测?

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

我知道这不是一个完全普遍的解决方案,(让人们解决他们的问题),但不幸的是我没有普遍修复的奢侈。

TIA

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

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

5 个答案:

答案 0 :(得分: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不同,你试图解析的语法是不明确的。

答案 1 :(得分:0)

一种方法:重建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);

答案 2 :(得分:0)

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

 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"}

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

答案 3 :(得分:0)

尝试此替换:

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

答案 4 :(得分:0)

我讨厌回答我自己的问题,正如你们中的许多人所指出的那样,正确地说,由于一个流浪的,未逃避的双引号字符注入了歧义,事后完全无法修复坏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;
}