我有一个类 Foo
应该以最人性化的方式序列化为文本文件,我使用 Ruby 的默认 YAML(Psych) 和自定义 encode_with
。我的问题是:如果我像这样删除 !ruby/object:Foo
:
def encode_with coder
coder.tag = nil
...
end
我能否以某种方式强制 Psych 将 map 加载为类 Foo
的对象(使用其 init_with
)。理想情况下,我也想删除 ---
文档标记。
当然,这很容易用 gsub
解决,但我想知道是否有一些 Psych 解决方案。不幸的是,Psych 并不是最好的 gem 记录。
最佳答案
您可以向 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
只是 Psych default parse method 的重新实现.而不是 default handler我在这里使用 MyHandler
。
MyHandler
的 start_mapping
方法覆盖了 TreeBuilder
的 default implementation .这是一个回调,当解析器在 YAML 中遇到 Map 时调用,并且文档根是一个 Map。因此,您只需将标签替换为根元素(不要为其他任何事情操心——这就是为什么我使用 @__root
变量来跳过进一步的修改)。
关于ruby - 强制 Psych 读取 YAML 映射作为给定类的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32104842/