【问题标题】:How do I have Ruby YAML dump a Hash subclass as a simple Hash?如何让 Ruby YAML 将 Hash 子类转储为简单的 Hash?
【发布时间】:2013-08-13 05:45:08
【问题描述】:

我有一个类 Foo,它是 Hash 的子类。

class Foo < Hash
  # whatever Foo-specific methods/etc
end

当我使用 YAML 将其转储到文件时,它会写有指示类的标签。

> f = Foo.new
> f[:bar] = "baz"
> puts YAML.dump(f)
--- !ruby/hash:Foo
:bar: baz

我希望它只写成一个普通的旧哈希(不是!ruby/hash:Foo

> puts YAML.dump({bar:"baz"})
---
:bar: baz

...这样我的数据的消费者就不需要知道Foo。是否有一种神奇的方法可以添加到我的类中以将其自身转换为序列化,或者有一个神奇的选项可以传递给 YAML.dump?

当然,将Foo 对象转换为散列很容易,但它们可能会嵌套在我想要转储的实际散列中的任何级别,我宁愿不必进行搜索并替换。

【问题讨论】:

  • 如果您显示示例代码、演示问题的示例 YAML 输出以及显示您希望其外观的示例输出,将会有所帮助。见sscce.org的“e”部分

标签: ruby hash yaml


【解决方案1】:

您可以使用(记录不充分的)encode_withrepresent_map 方法来实现此目的。要自定义对象的 YAML 序列化,请为其提供 encode_with 方法,该方法接受 coder 对象,其中方法之一是 represent_map

class Foo < Hash

  # other methods ...

  def encode_with coder
    coder.represent_map nil, self
  end

end

现在YAML.dump 只会将您的对象作为普通哈希输出。

然而

有点问题,因为有一个错误会导致此失败,并且是only fixed in the latest Gem version of Psych。它在当前最新的 Ruby 版本 (ruby 2.0.0p247) 中修复。 is fixed in Ruby trunk 所以以后的补丁版本应该没问题。

为了使用它,您必须确保您使用的是最新的 Psych Gem,而不是与 Ruby 捆绑在一起的版本。这应该很简单

gem 'psych', '2.0.0'

在您需要 Yaml 之前,但似乎在 Ruby 2.0 中由于某种我无法弄清楚的原因,这不起作用。不过,使用 Bundler 指定 Gem 版本确实有效,因此您可能需要创建一个 Gemfile 并在其中指定 Psych(如果您尚未使用它)。

【讨论】:

  • 这可能是正确的答案......现在,我的 ruby​​ 1.9.3 代码库,我猜我需要实现搜索和替换。
【解决方案2】:

搜索和替换其实还不错:

# Convert Hash/Array subclasses into plain hashes/arrays for YAML dump.
# Assumptions:
#   Hash keys will be simple objects - don't need to clear them
#   No custom objects containing Hash/Array subclass instances
def deep_clear_subclasses(obj, dedup = {})
  case obj
  when Hash
    return dedup[obj] if dedup.has_key? obj
    dedup[obj] = copy = {}
    obj.each {|k,v| copy[k] = deep_clear_subclasses(v, dedup)}
    copy
  when Array
    return dedup[obj] if dedup.has_key? obj
    obj.inject(dedup[obj] = []) {|a,v| a << deep_clear_subclasses(v,dedup)}
  else
    obj # not going to operate on other kinds of objects
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-03
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 2012-12-20
    • 2011-06-16
    • 2013-12-27
    相关资源
    最近更新 更多