2013-06-20 14 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

相關問題