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

发布于 2024-10-25 07:22:01 字数 772 浏览 2 评论 0原文

当我将数组或哈希分配给 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]}

嵌套哈希也会发生这种情况(例如,在数组或其他哈希内部)。在这种情况下有没有办法保留符号?

解决方案

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

When I assign an Array or Hash to an attribute of a Mongo document, it gets properly
serialized except for Symbols when they are used as Hash keys. Simple example:

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]}> 

Please, note that some_attr is retrieved as {"a"=>[:b, :c]}, not as
{:a=>[:b, :c]}

This also happens for nested Hashes (e.g., inside of Arrays or other Hashes). Is there a way to preserve Symbols in such cases?

Solution

I'm using YAML to manually serialize some_attr - YAML.dump (or Object#to_yaml) before storing, and YAML::load after reading the attribute. YAML preserves the serialized object better. ActiveRecord is using YAML to implement its serialize class method on ActiveRecord::Base.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

趁年轻赶紧闹 2024-11-01 07:22:01

这很可能与您用来为模型提供持久层的 ORM 有关。您可以使用一个方法包装 some_attr,该方法以 HashWithIn DifferentAccess 的形式返回它,然后您可以使用字符串或数组访问它。由于您使用的是 Rails,因此可以通过调用 Hash 对象上的 with_in Different_access 方法来激活此功能。 (如果你有一个 Hash 对象数组,当然你需要对每个对象调用它)该方法将返回相同的哈希值,但符号查找将起作用。

从您的代码:

new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a'] 

希望这有帮助!

More than likely this has to do with the ORM you are using to provide the persistance layer for the model. You can probably wrap some_attr with a method that returns it in the form of a HashWithIndifferentAccess which you can then access with either strings or arrays. Since you are using Rails, this functionality can be activated by calling the with_indifferent_access method on the Hash object. (If you have an array of Hash objects, you'll need to call it on each one of course) The method will return the same hash, but then symbol lookups will work.

From your code:

new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a'] 

Hope this helps!

缱倦旧时光 2024-11-01 07:22:01

这里的罪魁祸首是 BSON 序列化。当您序列化用作哈希键的符号时,它实际上会被转换为字符串,当您返回它时,您会得到字符串而不是符号。

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

不幸的是,我不在 Rails 上,所以我无法按照 ctcherry 的建议使用 with_in Different_access

the culprit here is the BSON serialization. when you serialize a symbol used as a key for hashes, it is actually translated to a string and when you ask it back you get the string instead of the symbol.

i'm having the same problem as you and i'm thinking of extending the Hash class to include a method to convert all the "string" keys to :symbols.

unfortunately i'm not on Rails so i cannot use the with_indifferent_access as suggested by ctcherry.

只怪假的太真实 2024-11-01 07:22:01

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

str.to_sym

I'm not sure about preserving symbols but you can convert the strings back to symbols.

str.to_sym
幽蝶幻影 2024-11-01 07:22:01

发现这个,效果很好,并且您已将该字段定义为哈希:

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

Found this, works well and you have define the field as Hash:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文