从 yaml 扩展哈希和(反)序列化
我找到了这个例子: http://www.yaml.org/YAML_for_ruby.html#extending_kernel::hash
很高兴看到 YAML 如何轻松地序列化哈希。 但是,我想序列化我自己的类,一个带有属性的扩展哈希。
yaml 字符串是什么样子以及序列化它的最佳方法是什么?
提前致谢
I found this example:
http://www.yaml.org/YAML_for_ruby.html#extending_kernel::hash
It's nice to see how easy YAML can serialize a hash.
However, I would like to serialize my own class, an extended hash WITH the attribute in it.
What would the yaml-string look like and what would be the best way to serialize it?
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以获取原始的来源
Hash#to_yaml
并覆盖它,添加您需要的任何内容:You can take the source of original
Hash#to_yaml
and override it, adding whatever you need:正如 Mladen Jablanović 的回答所示,您可以覆盖
to_yaml
。您可以添加一个名为“attributes”的数组(如果哈希中存在具有该名称的键,请特别注意转义该名称(如果...等,请注意转义转义的名称))。然而,您需要一些内部知识才能完成这项工作(out.map(tag_uri, to_yaml_style)
及其变体非常重要,并且没有很好的文档记录:各种 Ruby 解释器的源代码是您最好的选择赌注)。不幸的是,您还需要覆盖反序列化过程。如何重用现有代码几乎完全没有文档记录。正如 此答案 中所示,您会发现需要添加
to_yaml_type
并使用YAML::add_domain_type
添加反序列化代码。从那里开始,您几乎要靠自己了:您需要编写半个 YAML 解析器来解析 yamled 字符串并将其转换为您的对象。可以解决这个问题,但是更简单的解决方案(我上次想要这个时实现的)是使哈希成为我的对象的属性,而不是扩展哈希。后来我意识到我实际上并没有实现 Hash 的子类。存储键值对的东西并不一定意味着它是哈希。如果您实现
:[]
、:[]=
和each
,您通常会在能够将对象视为好像它是一个哈希值。As Mladen Jablanović's answer shows, you can override
to_yaml
. You could add an array named 'attributes' (taking special care to escape that name if there is a key in the hash with that name (taking care to escape the escaped name if ... etc.)). However, you need some knowledge of the internals to make this work (theout.map(tag_uri, to_yaml_style)
and its variations are nontrivial and not well documented: the sources of the various Ruby interpreters are your best bet).Unfortunately, you also need to override the deserialization process. How you can reuse existing code there is close to completely undocumented. As in this answer, you see you would need to add a
to_yaml_type
and add the deserialization code usingYAML::add_domain_type
. From there, you are pretty much on your own: you need to write half a YAML parser to parse the yamled string and convert it into your object.It's possible to figure it out, but the easier solution, that I implemented last time I wanted this, was to just make the Hash an attribute of my object, instead of extending Hash. And later I realized I wasn't actually implementing a subclass of Hash anyway. That something is storing key-value pairs doesn't necessarily mean it is a Hash. If you implement
:[]
,:[]=
andeach
, you usually get a long way towards being able to treat an object as if it is a Hash.