0

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

字符串示例:

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

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

起初,我想 - 只是做:

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

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

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

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

TIA

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

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

4

5 回答 5

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 不同,您尝试解析的语法是模棱两可的。

于 2013-06-20T20:08:16.647 回答
0

试试这个替换:

repl = str.replace(/"(?= )/g, "\\\"");
于 2013-06-20T18:48:19.827 回答
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;
}
于 2013-06-22T13:21:43.080 回答
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, '&quot;');
 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&quot; pizza: which can also contain other &quot;,&quot; which would break in a one liner regex.

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

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

于 2013-06-20T18:41:54.340 回答
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);
于 2013-06-20T18:39:41.753 回答