【问题标题】:extending to_json for a subclass of Hash为 Hash 的子类扩展 to_json
【发布时间】:2013-01-26 07:06:50
【问题描述】:

我有一个 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?',但这似乎不是正确的方法。)

【问题讨论】:

    标签: ruby json


    【解决方案1】:

    你能做到吗:

    class ExtendedHash < Hash
      attr_accessor :f
    
      def to_json(*args)
        Hash[self].merge(:f => f).to_json(*args)
      end
    end
    

    【讨论】:

    • 好吧,也许吧。 f 字段旨在与任何键值对分开,因此如果哈希已经有一个名为“f”的键,则上述操作将失败。我可以使用在实践中不太可能使用的混淆密钥,例如 (:i0have0no0life0 =&gt; f),但它没有通过气味测试。
    • @fearless_fool 你仍然会使用相同的方法,尽管如果你想将它与哈希分开,我怀疑哈希子类是放置它的正确位置——我会组成一个新类如果您的课程将公开非哈希值。
    • @DaveNewton:公平点。 Hash 的子类在我的情况下感觉不错,因为我想要一些可以完成哈希所做的所有事情的东西。但我想出了一个还不错的解决方案(这里的其他地方)。
    【解决方案2】:

    以下是正确的:

    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_create() 方法中显式调用 JSON.load

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

    【讨论】:

      猜你喜欢
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多