如何让Ruby YAML将散列子类转储为简单散列?
我有一个类如何让Ruby YAML将散列子类转储为简单散列?,ruby,hash,yaml,Ruby,Hash,Yaml,我有一个类Foo,它是Hash的子类 class Foo < Hash # whatever Foo-specific methods/etc end 我希望它只是作为一个普通的旧散列来编写(而不是!ruby/hash:Foo) …这样我的数据的消费者就不需要知道Foo。是否有一个神奇的方法添加到我的类中以转换自身进行序列化,或者有一个神奇的选项传递到YAML.dump 当然,将一个Foo对象转换为散列是很容易的,但是它们可能会嵌套在我想要转储的实际散列中的任何级别上,我宁愿不必进行
Foo
,它是Hash
的子类
class Foo < Hash
# whatever Foo-specific methods/etc
end
我希望它只是作为一个普通的旧散列来编写(而不是!ruby/hash:Foo
)
…这样我的数据的消费者就不需要知道Foo
。是否有一个神奇的方法添加到我的类中以转换自身进行序列化,或者有一个神奇的选项传递到YAML.dump
当然,将一个
Foo
对象转换为散列是很容易的,但是它们可能会嵌套在我想要转储的实际散列中的任何级别上,我宁愿不必进行搜索和替换。您可以使用(文档不全的)encode\u with
和representation\u map
方法来实现这一点。要自定义对象的YAML序列化,请为其提供一个encode\u with
方法,该方法接受一个对象,其中一个方法是
在您需要Yaml之前,但在Ruby 2.0中,这似乎不起作用,原因我无法理解。不过,使用Bundler指定Gem版本确实有效,因此如果尚未使用它,您可能需要创建一个
Gem文件并在其中指定Psych。搜索和替换实际上还不错:
# 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
#将散列/数组子类转换为用于YAML转储的普通散列/数组。
#假设:
#散列键将是简单的对象-不需要清除它们
#没有包含哈希/数组子类实例的自定义对象
def deep_clear_子类(obj,dedup={})
案例obj
当散列
如果dedup.has_key,返回dedup dedup[obj]?obj
重复数据消除[obj]=复制={}
obj.each{k,v|copy[k]=deep_clear_子类(v,dedup)}
复制
当数组
如果dedup.has_key,返回dedup dedup[obj]?obj
obj.inject(dedup[obj]=[]){a,v | a这可能是正确的答案……现在,对于我的ruby 1.9.3代码库,我猜我需要实现搜索和替换。如果您展示示例代码、演示问题的示例YAML输出和显示您希望它的外观的示例输出,这会有所帮助。请参阅
> puts YAML.dump({bar:"baz"})
---
:bar: baz
class Foo < Hash
# other methods ...
def encode_with coder
coder.represent_map nil, self
end
end
gem 'psych', '2.0.0'
# 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