我有一个类Foo
应该以最人性化的方式序列化为文本文件,我使用Ruby的默认YAML(Psych)和自定义encode_with
。我的问题是:如果我这样删除!ruby/object:Foo
:
def encode_with coder
coder.tag = nil
...
end
我还能以某种方式强迫Psych将地图加载为类Foo
的对象(使用其init_with
)。理想情况下,我也想删除---
文档标记。
当然,使用gsub
很容易解决,但我想知道是否有一些心理解决方案。不幸的是,Psych并不是宝石中最好的记录。
答案 0 :(得分:5)
您可以向Psych提供自己的Handler
:
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
一些文档。 my_parse
只是对心理default parse method的重新实施。而不是default handler我在这里使用MyHandler
。
MyHandler
start_mapping
方法会覆盖TreeBuilder
&#39; s default implementation。这是一个回调,当解析器在YAML中碰撞到Map时调用,而文档根是一个Map。因此,您只需要为根元素交换标记(并且不要为其他所有内容而烦恼 - 这就是我使用@__root
变量跳过进一步修改的原因)。