2012-11-08 42 views
2

其他人有這個問題?哈希to_json和後面不保留散列作爲關鍵?

hash_as_key = {'one' => 1, 'two' => 2} 
outer_hash = {hash_as_key => 3} 

outer_hash.keys[0].class 
=> Hash 

as_json = outer_hash.to_json 
back_to_obj = JSON.parse(as_json) 

back_to_obj.keys[0] 
=> "{\"one\"=>1, \"two\"=>2}" 
back_to_obj.keys[0].class 
=> String 

如果你有一個Hash對象,其中的關鍵是散列本身,轉換成JSON並恢復到Ruby對象似乎轉動鑰匙爲一個字符串。

+0

解決方法:JSON只支持字符串作爲鍵,但我們發現在Ruby中的YAML解析器似乎來回轉換沒關係,'YAML :: load(outer_hash.to_yaml)',雖然我不確定這是100%安全的。 – hgcrpd

回答

3

keys in JSON objects are strings沒有別的:

對象是一個無序的名稱/值對。一個對象以{(左大括號)開頭,以}(右大括號)結尾。每個名稱後跟:(冒號),名稱/值對由,(逗號)分隔。

enter image description here

所以當你的數據結構轉換成JSON鑰匙會很快成爲字符串。然後,一旦您的數據使用JSON,您的密鑰的原始類型信息將會丟失。

Ruby的哈希比JSON的對象更加靈活一般,所以不是每個Ruby哈希都可以用JSON表示。如果您將JSON作爲數據存儲和傳輸的目標,那麼您必須將數據限制爲JSON支持的數據或將數據轉換爲與JSON兼容的結構。

如果你看一下中間JSON你會看到這是怎麼回事:

> puts outer_hash.to_json 
{"{\"one\"=>1, \"two\"=>2}":3} 

所以關鍵是串'{"one"=>1, "two"=>2}'因爲那是什麼hash_as_key.to_s給你。同樣,數字鍵將to_s被字符串化而失去其「numberness」:

> {1 => 2}.to_json 
=> "{\"1\":2}" 
+0

我知道JSON格式不能存儲Ruby哈希的額外靈活性,但是如果給定JSON的約束,Ruby預期將會重新創建原始Ruby對象嗎?或者這會導致模棱兩可 - 即我是否希望密鑰是哈希,或者只是一個帶有「{」的字符串? – hgcrpd

+0

@hgcrpd:你不能在JSON中表示所有的Ruby哈希,所以你會被猜測和試圖根據數據中的模式和關於'to_s'行爲的假設來推斷intent。當你堅持合理的可能性時,預期的結果並不重要。 –