本文介绍了强制 Psych 将 YAML 映射读取为给定类的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类 Foo 应该以最人性化的方式序列化为文本文件,我使用 Ruby 的默认 YAML(Psych) 和自定义 encode_with.我的问题是:如果我像这样删除 !ruby/object:Foo :

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

我还能以某种方式强制 Psych 加载地图作为 Foo 类的对象(使用它的 init_with).理想情况下,我也想删除 --- 文档标记.

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.

当然,用gsub很容易解决这个问题,但我想知道是否有一些Psych解决方案.不幸的是,Psych 并不是关于宝石的最佳记录.

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.

推荐答案

您可以向 Psych 提供您自己的 Handler:

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

一些文档.my_parse 只是 Psych 默认解析方法.我使用 MyHandler默认处理程序/code> 在这里.

A bit of documentation. my_parse is just a re-implementation of Psych default parse method. Instead of default handler I use MyHandler here.

MyHandlerstart_mapping 方法覆盖了 TreeBuilder默认实现.这是一个回调,当解析器遇到 YAML 中的 Map 时调用,文档根一个 Map.所以你只需要交换根元素的标签(不要打扰其他一切——这就是为什么我使用 @__root 变量来跳过进一步的修改).

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).

这篇关于强制 Psych 将 YAML 映射读取为给定类的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 12:19