I have a class Foo that is supposed to be serialized to a text file in most human-friendly way possible, I use Ruby's default YAML(Psych) with custom encode_with. My question is: if I remove !ruby/object:Foo like so:
def encode_with coder
coder.tag = nil
...
end
can I somehow still force Psych to load a map as object of class Foo(using its init_with). Ideally, I'd like to remove --- document mark as well.
Of course, this is easy to solve with gsub, but I wonder if there is some Psych solution for this. Unfortunately, Psych isn't the best documented of gems.
You can provide your own Handler to Psych:
class MyHandler < Psych::Handlers::DocumentStream
def start_mapping(anchor, tag, implicit, style)
unless @__root
tag = "!ruby/hash:MyHash"
@__root = true
end
super anchor, tag, implicit, style
end
end
class MyHash < Hash
end
def my_parse(yaml)
parser = Psych::Parser.new(MyHandler.new{|node| return node})
parser.parse yaml
false
end
# {a: 1, b: {c: 2, d: 3}, c: [1,2,3]}.to_yaml
str = "---\n:a: 1\n:b:\n :c: 2\n :d: 3\n:c:\n- 1\n- 2\n- 3\n"
result = my_parse(str).to_ruby
puts result.class # => MyHash
A bit of documentation. my_parse is just a re-implementation of Psych default parse method. Instead of default handler I use MyHandler here.
MyHandler's start_mapping method overrides TreeBuilder's default implementation. This is a callback which is called when parser bumps into Map in YAML, and document root is a Map. So you just need to swap the tag for the root element (and don't bother with everything else – that's why I use @__root variable to skip further modifications).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With