Marshal加载一个Hash子类的marshal dumped实例

时间:2013-02-22 16:15:51

标签: ruby serialization marshalling

我无法管理Marshal.load哈希子类的Marshal.dump ed实例:

class MarshalDumpableHash < Hash

  def initialize(constructor = {})
    if constructor.is_a?(Hash)
      super()
      update(constructor)
    else
      super(constructor)
    end
  end

  def marshal_dump
    p self
    self
  end

  def marshal_load(hash)
    p hash
    update(hash)
  end

end


h = { asd: 'ciao' }

p MarshalDumpableHash.new(h) #=> {:asd=>"ciao"}
p Marshal.dump(MarshalDumpableHash.new(h)) #=> "\x04\bU:\x18MarshalDumpableHash@\x00"

p Marshal.load(Marshal.dump(MarshalDumpableHash.new(h))) #=> {} WHY?

我觉得奇怪的是,p self方法中的marshal_dump打印{:asd=>"ciao"},而marshal_load方法中的{}打印{{1}}

1 个答案:

答案 0 :(得分:2)

返回marshal_dump的方法self不是使用marshal_dumpmarshal_load的用例,因为内置转储和加载会这样做。因此,如果您只想编组self,则无需编写任何自定义marshal_dumpmarshal_load

class Subclassed < Hash
end

s = Subclassed.new
s[:foo] = :bar
Marshal.load(Marshal.dump(s)).class #=> Subclassed

当您在加载转储对象时不想重新加载的对象上有剩余信息时,这些方法适用于用例。这是为了节省空间。例如:

class Subclassed < Hash

  attr_reader :surplus_info

  def initialize(surplus_info)
    @surplus_info = surplus_info
  end

  def marshal_dump
    Hash.new.merge(self)
  end

  def marshal_load other
    update(other)
  end
end

如果没有marshal_dumpmarshal_load,生成的编组字符串将为:

"\004\bIC:\017Subclassed{\006:\bfoo:\bbar\006:\022@surplus_info\"\bfoo"

哪个有剩余信息。使用marshal加载和转储,您将能够减少编组字符串:

"\004\bIU:\017Subclassed{\006:\bfoo:\bbar\000" 

这是这些方法的目的。此外,ruby doc州:

  

marshal_dump可能会导致Marshal字符串变小。

此外,有关使用marshal_dump

的文档有点模糊
  

转储对象时,将调用方法marshal_dump。 marshal_dump必须返回包含marshal_load所需信息的结果,以重建该对象。结果可以是任何对象。

它应该是“结果可以是除self之外的任何对象”。我不知道在self中返回marshal_dump时行为ruby显示的是非常有意的(至少一个错误会很好),或者它是否被遗忘,因为它实际上不是一个用例。