ruby - 强制 Psych 读取 YAML 映射作为给定类的对象

标签 ruby serialization yaml

我有一个类 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

MyHandlerstart_mapping 方法覆盖了 TreeBuilderdefault implementation .这是一个回调,当解析器在 YAML 中遇到 Map 时调用,并且文档根一个 Map。因此,您只需将标签替换为根元素(不要为其他任何事情操心——这就是为什么我使用 @__root 变量来跳过进一步的修改)。

关于ruby - 强制 Psych 读取 YAML 映射作为给定类的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32104842/

相关文章:

ruby-on-rails - 确保 Rollbar 已使用 RSpec 报告错误

ruby-on-rails - 为什么没有显示 Rails 错误?

java - Array<Vector2> 的 Libgdx JSON 自定义序列化

docker - curl 命令参数上的YAML解析错误

ruby-on-rails - rails 响应跨域请求在本地开发,spotify 应用程序开发

entity-framework - 防止 Entity Framework 序列化 EntityKey、EntitySetName 等

java kryo 3.0.3 对象的序列化速度较低

python - 读取 YAML 文件并创建 Python 对象

python - YAML 和元组作为 dict 键

ruby-on-rails - 如何以 root 身份从 Rails 运行命令?