2013-06-20 16 views
0

我有一个问题,有人不正确地转义值后面的双引号被解释为JSON字符串。JavaScript的正则表达式替换字符串中的所有双引号,除非双引号后跟空格或逗号空格

字符串例如:

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

当我努力JSON.parse()来处理这个它给因为转义双引号的错误(指的以英寸为单位的大小)

在第一,我想 - 只是这样做:

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

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

有人可以帮助构建一个正则表达式来寻找(替换)任何序列的双引号其中接下来的双字符序列后面的违法doubleqoute是不是太空逗号?

我知道这不是一个全面的解决方法,(让人去修复他们的结局),但不幸的是,我没有一个通用的解决方案。

TIA

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

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

+2

这在创作时会做得更好;你怎么创建你的_JSON_? –

+0

当你使用JSON.stringify把你的“东西”变成一个json对象时,它应该为你做自动转义。你不需要自己做这个;你能否展示你如何构建你首先变成JSON的对象? –

+1

你所要求的正则表达式不会解决你的问题,因为在'description','this'和'value'这两个单词前面的双引号不应该被转义,但是不会立即跟随逗号或空格字符。 – gatkin

回答

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

这是很好的,如果你的某些描述内容,因为价值:{“描述”:“这,”披萨“,”是我的12“披萨”,我下令。“,”价值“:”1“}不适用于这个解决方案,但它在我的上面。 – Drew

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

注意如果说描述这种方法不会破还包含的任何图案的,你可能在使用的正则表达式一个衬垫

0

的一部分尝试这种替换:

repl = str.replace(/"(?=)/g, "\\\""); 
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”,“关闭”等用绳子不太可能发生的输入,甚至控制字符,如果你不介意的正则表达式是神秘。但正如其他人所指出的,没有任何解决方案可以在所有情况下都能正常工作。不管你做什么,在描述文本中都会有一个值会让你感到困惑,因为与正确生成的JSON不同,你试图解析的语法是不明确的。

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; 
} 
+0

如果这可以用正则表达式来完成 - 那就是答案。 – Ross

相关问题