我有一个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
? (我看过'How can I use Ruby's to_json in a subclass and include super's json?',但这似乎不是正确的做法。)
答案 0 :(得分:1)
class ExtendedHash < Hash
attr_accessor :f
def to_json(*args)
Hash[self].merge(:f => f).to_json(*args)
end
end
答案 1 :(得分: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.load
方法中显式调用json_create()
。
我可以忍受,但也许有更好的方法。