2015-04-24 56 views
2

我遇到了由JavaScript腳本生成的JSON在由JavaScript解析時不兼容的問題JSON.parse。考慮以下示例:Ruby生成的JSON與JavaScript的JSON解析器不兼容

# Ruby 
require 'json' 
hash = {} 
hash["key"] = "value with \u001a unicode" 
hash.to_json 
=> '{"key":"value with \u001a unicode"}' 

// JavaScript 
JSON.parse('{"key":"value with \u001a unicode"}') 
=> JSON.parse: bad control character in string literal at line 1 column 2 of the JSON data 

問題是Unicode字符\u001a。解決方法是將\u001a轉換爲\\u001a,但事情是,\u001a被Ruby自動插入到字符串中。我無法可靠地後處理結果。任何關於如何解決這個問題的想法?

請注意,我希望在JavaScript執行環境中調用JSON.parse,而不是在Ruby的解釋器中。

+0

我跑你的代碼,我實際上得到這個輸出:'=>「{\」key \「:\」值與\\ u001a unicode \「}」' –

+0

我也運行你的代碼,它的工作精細。 –

+1

您正在查看終端中的輸出。 '\\ u001a'是終端是物理字符串'\ u001a'。 Ruby將反斜槓顯示爲\\,因此您可以區分單個字符「\ u001a」和寫入「\ u001a」的六個字符串。 – Max

回答

2

短的版本是,你解釋你的字符串作爲一個JavaScript表達式試圖把它作爲JSON解碼之前。

U + 001A是一個控制字符。 RFC 4627 explicitly disallows control characters U+0000-U+001F in quoted strings。這裏的問題不是JSON無效,而是在嘗試將它們解析爲JSON之前,您正在消除控制字符。

當您從Ruby轉儲字符串"\u001a"並將其複製並粘貼到Javascript解釋器中時,轉義序列轉換爲未轉義的控制字符,這不是JSON中的有效字符!非禁止的字符工作得很好 - 例如,您可以愉快地JSON.parse('["\u0020"]')

但是,如果你不是將該字符串解釋爲Javascript,而是將其作爲原始字節讀取,它將正確解析。

$ irb 
irb(main):001:0> require 'json' 
=> true 
irb(main):003:0> open("out.json", "w") {|f| f.print JSON.dump(["\u001a"]) } 
=> nil 

$ node -e 'require("fs").readFile("out.json", function(err, data) { console.log(JSON.parse(data)); });' 
[ '\u001a' ] 

如果你想成爲的複製粘貼,你需要複製一個逃脫版本字符串,這樣當該字符串是由您的Javascript引擎,轉義雙轉義序列解析正確地逃避序列而不是字符。因此,您應該複製puts JSON.dump(["\u001a"]).inspect的輸出,而不是複製JSON.dump(["\u001a"])的輸出,它將正確地轉義字符串中的任何轉義序列。

+0

有沒有辦法寫出正確轉義的字符串版本?我正在將字符串寫入文件,然後其他人正在讀取該文件並將該字符串複製到JavaScript文件中(以編程方式)。 – Max

+0

如果你用Javascript寫出'JSON.stringify(json_string)'。如果你使用Ruby編寫'JSON.dump(json_string)'。 –

0

對我來說,下面的ruby代碼給出了輸出中的"{\"key\":\"value with \\u001a unicode\"}"

而且JSON.parse也通過它。並給出Object {key: "value with unicode"}

+0

您正在查看終端中的代碼。它逃避顯示字符串,所以你可以看到字符。否則,你怎麼能說出'\\ u001a'和'\ u001a'之間的區別。所以'\\ u001a'是沒有unicode轉義的字符串'\ u001a'。要查看差異,請比較'「\\ u001a」.size'和'「\ u001a」.size'的結果。請注意'\\ u001a'的長度是6 * not * 7,這意味着Ruby正在顯示'\'轉義。 – Max

+0

你是對的。我的錯。 –

0

按照RFC

JSON文本是以Unicode編碼。默認的Unicode是utf-8。

我跑IRB你的代碼,並得到如下:

1.9.3-p484 :001 > require 'json' 
=> true 
1.9.3-p484 :002 > 
1.9.3-p484 :003 > hash = {} 
=> {} 
1.9.3-p484 :004 > hash["key"] = "value with \u001a unicode" 
=> "value with \u001A unicode" 
1.9.3-p484 :005 > hash.to_json 
=> "{\"key\":\"value with \\u001a unicode\"}" 

然後運行返回的字符串在JavaScript控制檯,我得到如下:

> JSON.parse("{\"key\":\"value with \\u001a unicode\"}") 
> Object {key: "value with unicode"} 

它返回一個目的。要獲得使用Unicode值,你必須通過調用訪問哈希:

> str = JSON.parse("{\"key\":\"value with \\u001a unicode\"}") 
> Object {key: "value with unicode"} 
> str.key 
> "value with unicode" 
+0

JSON.parse應該在JavaScript執行環境中執行,而不是在Ruby的解釋器中執行。 – Max

+0

@Max其實,這也可以。只需[複製粘貼到Chrome的控制檯](http://i.imgur.com/EDIDkUF.png)。那些甚至是不同的語言!..無論如何。 –

+0

如果您想要解釋爲什麼Ruby的控制檯輸出能夠正常工作,可以在@D端查看已接受的答案。控制檯輸出不是'to_json'調用返回的確切字符串。 – Max