开发者

Extending Hash and (de)serializing from/to yaml

开发者 https://www.devze.com 2023-04-04 05:57 出处:网络
I found this exampl开发者_StackOverflow社区e: http://www.yaml.org/YAML_for_ruby.html#extending_kernel::hash

I found this exampl开发者_StackOverflow社区e: 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


You can take the source of original Hash#to_yaml and override it, adding whatever you need:

def to_yaml( opts = {} )
  YAML::quick_emit( self, opts ) do |out|
    out.map( taguri, to_yaml_style ) do |map|
      # here you can add something like:
      map.add('my_attribute', @my_attribute)
      # and proceed with the usual Hash serialization:
      each do |k, v|
        map.add( k, v )
      end
    end
  end
end


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 (the out.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 using YAML::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 :[], :[]= and each, you usually get a long way towards being able to treat an object as if it is a Hash.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号