0

新しいフィールド f を追加する Hash のサブクラスがあります。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 をサブクラスで使用し、スーパーの 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.loadれ、json_create()メソッドでを明示的に呼び出す必要があります。

私はそれと一緒に暮らすことができますが、もっと良い方法があるかもしれません。

于 2013-01-25T23:06:50.343 に答える