2013-08-16 44 views
3

我遇到了一個奇怪的小問題,它解析了一些帶有引號的JSON。我正在使用本機JSON.stringify和JSON.parse函數來執行此操作。如果我將一個對象中帶有引號的對象串起來,他們會像預期的那樣被轉義。如果我把它解析回一個對象,它再次正常工作。JSON.stringify /用引號解析奇怪點

問題發生在我將字符串化,然後將對象打印到頁面,然後解析生成的字符串。如果我嘗試這樣做,解析函數將失敗,因爲stringify在每個違規引號之前只放了一個斜線。

我需要實現這個目標的原因是我正在處理一個應用程序,該應用程序將存儲在數據庫中的內容動態加載爲JSON字符串。某些時候需要將字符串打印到頁面上,以便javascript可以找到它們並根據其內容構建頁面。我需要一些強大的將對象傳入和傳出字符串的方法,如果用戶輸入了錯誤的字符,這些字符串不會失敗!

我可以通過用替換調用在代碼中插入額外的斜槓來解決此問題,但我想知道是否有更好的方法來處理這個問題?

我已經把一對夫婦jsfiddles來說明什麼,我試圖描述:

http://jsfiddle.net/qwUAJ/(字符串化然後解析回)

var ob = {}; 
ob["number1"] = 'Number "1"'; 
ob["number2"] = 'Number 2'; 
ob["number3"] = 'Number 3'; 

var string = JSON.stringify(ob); 
var reOb = JSON.parse('{"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"}'); 

$('div').html(string); 

http://jsfiddle.net/a3gBf/4/(字符串化,然後打印,然後解析回)

// Make an object 
var ob = {}; 
ob["number1"] = 'Number "1"'; 
ob["number2"] = 'Number 2'; 
ob["number3"] = 'Number 3'; 

// Turn the object into a JSON string 
var string = JSON.stringify(ob); 

// Printing the string outputs 
// {"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"} 
$('.stringified').html(string); 

// Attempt to turn the printed string back into an object 
var reOb = JSON.parse('{"number1":"Number \"1\"","number2":"Number 2","number3":"Number 3"}'); 

// This fails due to the single escaped quote marks. 

感謝您提前給予任何幫助!

+0

我認爲'replace()'是給出'JSON.stringify'輸出的唯一選項。 –

+1

您正在將控制檯輸出中的文本複製到代碼中。你爲什麼要這樣做,而不是使用'string'變量?據我所知,瀏覽器中的輸出以瀏覽器認爲合適的方式顯示,甚至可能無法在代碼中有效(儘管如此,還不是100%)。例如,當你執行'JSON.parse(string);'時,它可以工作,然後執行'console.log(reOb)',你也可以看到新的輸出是:'Object {number1:「Number」1「」,number2 :「Number 2」,number3:「Number 3」}'由於'Number「1」「'中的重複引號,它甚至不會在代碼中解析。 – Nope

+1

我不明白這個問題。爲什麼你第二次手動輸入字符串? http://jsfiddle.net/a3gBf/3/ –

回答

7

這是源於重新評估字符串不首先把它放回一個字符串字面一個問題,所以意義的變化,如果它甚至仍然有效。
你需要考慮'\"'作爲一個文字實際上是什麼意思?答案是",沒有\。爲什麼?

  • \"如果你想有\"爲文本的結果解析爲"

,你需要寫'\\\"'

  • \\解析\
  • \"解析"

所以基本上,額外的斜槓是需要轉義任何帶有特殊含義的字符字符串文字

如果您確實var reOb = JSON.parse($('.stringified').html());它會正常工作。


進一步考慮

str = '\\\"\\\'';  //  \"\' 
str = '\"\'';   //  "' 
str = '"'';   // SyntaxError: Unexpected token ILLEGAL 

據我所知,的JavaScript沒有提供原生實現轉換字符串根據需要,所以我知道最簡單的方法是使用replace

function toLiteral(str) { 
    var dict = {'\b': 'b', '\t': 't', '\n': 'n', '\v': 'v', '\f': 'f', '\r': 'r'}; 
    return str.replace(/([\\'"\b\t\n\v\f\r])/g, function ($0, $1) { 
     return '\\' + (dict[$1] || $1); 
    }); 
} 
toLiteral('foo\\bar'); // "foo\\bar" 
+0

嗨保羅,我意識到他們是必需的,並明白他們做什麼,我想我問是否有一種方法stringify輸出一個預先轉義的字符串,或至少一個字符串,我不必重新處理替換()或類似之前,它可以被解析? – Gruffy

+1

內存中的_String_不需要任何更改就可以在'JSON.parse'中正常工作,它是在重新評估它之前不會變成_String_文字的結果字符串,需要任何反斜槓,引號,新行等逃避回到文字。 –

+0

@Gruffy如果你以後用getJSON或$ .get獲取它,那麼你將字符串保存在一個數據庫中,然後在JS將它串化後,你只需提供JSON。如果你用你的PHP生成JS代碼,那麼它變得更加複雜。 – HMR

2

如果生成JS wi你應該在你的JSON字符串中避開引號:

//PHP code generating js code 
echo "var myJSONString = \"". str_replace("\"","\\\"",$mySqlJSON)."\";"; 
+0

感謝您使用基於PHP的解決方案,但我期望通過JS來完成此操作,以適應應用程序構建/交付給我的方式! – Gruffy

+0

@Gruffy它怎麼樣?你已經提到將JSON字符串保存在數據庫中,但沒有提到如何提供它。如果您將保存的JSON作爲JS提供服務,或者不會像Paul提到的那樣生成有效的JS(您將得到語法錯誤),則必須以這種方式轉義JSON字符串。 – HMR

+1

@Gruffy如果您以後希望將JSON作爲JSON提供服務並使用$ .get或$ .getJSOn從您的頁面請求它,那麼您遇到了麻煩,因爲您的數據庫中充滿了無效的JSON(您已將其設置爲無效由Paul提供的JS替換方法)。 – HMR