用作哈希键的符号在序列化时会转换为字符串

时间:2011-03-20 18:49:04

标签: ruby-on-rails ruby mongodb mongoid

当我将一个数组或哈希分配给Mongo文档的属性时,它会正常运行 序列化除了符号,当它们用作哈希键时。简单的例子:

irb>MyMongoModel.create :some_attr => {:a => [:b,:c]} 
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {:a=>[:b, :c]}> 

irb>MyMongoModel.last 
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {"a"=>[:b, :c]}> 

请注意,some_attr被检索为{"a"=>[:b, :c]},而非{:a=>[:b, :c]} some_attr

对于嵌套的哈希(例如,在阵列或其他哈希中)也会发生这种情况。在这种情况下,有没有办法保留符号?

解决方案

我正在使用YAML在存储之前手动序列化Object#to_yaml - YAML.dump(或serialize),并在读取属性后使用YAML :: load。 YAML更好地保留了序列化对象。 ActiveRecord正在使用YAML在ActiveRecord::Base上实现其{{1}}类方法。

4 个答案:

答案 0 :(得分:4)

这很可能与您用于为模型提供持久层的ORM有关。您可以使用以some_attr形式返回HashWithIndifferentAccess的方法来包装with_indifferent_access,然后您可以使用字符串或数组进行访问。由于您使用的是Rails,因此可以通过调用Hash对象上的new_hash = MyMongoModel.last.some_attr.with_indifferent_access new_hash[:a] # Will return the same as new_hash['a'] 方法来激活此功能。 (如果你有一个Hash对象数组,你当然需要在每个对象上调用它)该方法将返回相同的哈希,但随后符号查找将起作用。

从你的代码:

{{1}}

希望这有帮助!

答案 1 :(得分:3)

这里的罪魁祸首是BSON序列化。当你序列化一个用作哈希键的符号时,它实际上被翻译成一个字符串,当你再问它时,你得到的是字符串而不是符号。

我遇到了和你一样的问题,我正在考虑扩展Hash类,以包含一个将所有“字符串”键转换为:symbols的方法。

不幸的是我不在Rails上,所以我不能按照ctcherry的建议使用with_indifferent_access

答案 2 :(得分:0)

我不确定是否保留符号,但您可以将字符串转换回符号。

str.to_sym

答案 3 :(得分:0)

发现这个,效果很好,你已经将字段定义为Hash:

https://github.com/mindscratch/mongoid-indifferent-access