0

我有一个 Hash 的子类,它添加了一个新字段 f。我希望 JSON 序列化和反序列化 f 以及散列本身的内容,但还没有弄清楚如何做到这一点:

Class ExtendedHash < Hash
  attr_accessor :f
end

当然,正如所写,ExtendedHash#to_json不保留 f 字段:

>> c = ExtendedHash[{:a => 1, :b => 2}]
=> {:a=>1, :b=>2}
>> c.f = 123
=> 123
>> c.to_json
=> "{\"a\":1,\"b\":2}"

那么什么是正确的定义:

  def to_json(*a)
    ...
  end
  def self.load_from_json(str)
    ...
  end
end

? (我看过“如何在子类中使用 Ruby 的 to_json 并包含 super 的 json?”,但这似乎不是正确的方法。)

4

2 回答 2

1

你能做这个吗:

class ExtendedHash < Hash
  attr_accessor :f

  def to_json(*args)
    Hash[self].merge(:f => f).to_json(*args)
  end
end
于 2013-01-25T22:17:06.980 回答
0

以下是正确的:

require 'json'

class ExtendedHash<Hash
  attr_accessor :f

  def to_json(*a)
    {
      'json_class' => self.class.name,
      'f' => f,
      'super' => super
    }.to_json(*a)
  end

  def self.json_create(s)
    self[JSON.load(s["super"])].tap {|o| o.f = s["f"]}
  end

end

它的工作原理是这样的:

> x = ExtendedHash["a", 1, "b", 2]
=> {"a"=>1, "b"=>2}
> x.f = 123
=> 123
> s = x.to_json
=> "{\"json_class\":\"ExtendedHash\",\"f\":123,\"super\":\"{\\\"a\\\":1,\\\"b\\\":2}\"}"
> y = JSON.load(s)
=> {"a"=>1, "b"=>2}
> y.f
=> 123

唯一奇怪的是底层哈希是“双重json”,即转换为JSON字符串,然后再次通过JSON运行。这会创建许多额外的转义字符,并且需要JSON.loadjson_create()方法中显式调用。

我可以忍受,但也许有更好的方法。

于 2013-01-25T23:06:50.343 回答