【问题标题】:Best way to find the class of an class attribute查找类属性的类的最佳方法
【发布时间】:2016-03-25 07:45:31
【问题描述】:

我和 Ruby 一起打了一个又一个的石头,但我一直在战斗。 今天我遇到了识别属性的问题。

我正在将对象序列化为 JSON,我的对象看起来像这样,其中属性 Items 是一个对象,其中包含 Item 类型的对象,而 address 是一个对象。

    module OrderSet
  class OrderObject

    attr_accessor :items, :url, :email, :address, :id

    def initialize args = nil
      if args != nil
        args.each do |k, v|
          instance_variable_set("@#{k}", v) unless v.nil?
        end
      end
    end

    def to_json
      hash = {}
      self.instance_variables.each do |var|
        # [1..-1] is to get rid of the leading @ from instance variables. This is so the API knows the variables.
        hash[var[1..-1]] = self.instance_variable_get var
      end
      hash.to_json
    end
  end
end

如果我序列化它,它会以这样的 JSON 结尾(抱歉,混乱,但它不会格式化,因为它不是有效的 JSON...:

"{"address":"{\"name\":\"Ruby\",\"line1\":\"StoneStreet\",\"city\":\"Gemstones\",\"country\":\"The WOrld\",\"postCode\":\"4004VC\"}","items":"[\"{\\\"productId\\\":\\\"canvas_a60x60\\\",\\\"files\\\":\\\"{\\\\\\\"content\\\\\\\":\\\\\\\"http://i.imgur.com/uHZfjIU.jpg\\\\\\\"}\\\",\\\"quantity\\\":10,\\\"pageCount\\\":1,\\\"metaData\\\":\\\"test\\\"}\"]","email":"test@test.test"}"

它的外观: "{"address":"{"name":"Ruby", "line1":"StoneStreet", "city":"Gemstones", "country":"The WOrld", "postCode":"4004VC" }","items":"["{
"productId":"canvas_a60x60", "files":"{"content":"http://i.imgur.com/uHZfjIU.jpg" }","quantity":10, "pageCount":1, "metaData":"test" }"]", "email":"test@test.test" }"

现在每个类都有自己的 to_json 方法,需要调用它并放入原始 to_json 方法的哈希中。我想出了一些解决方案:

  1. 做一个object.is_a?(ClassName)
  2. 检查模块(我有 4 个模块,总共包含大约 20 个类,所以第一个比第二个长得多)
  3. 创建一个基础对象,将所有其他对象扩展到该基础对象,检查它是否是基础对象的子对象并相应地调用 to_json(将 to_json 放在父对象中)
  4. 也许是一个静态方法,但我不知道它是否会像它调用instance_variables那样工作

[编辑] 哎呀,忘了问这个问题,有没有比上述方法更好的方法,如果没有,上面哪一个是最好的?

【问题讨论】:

  • 检查这些项目的类和JSON序列化有什么联系?
  • @FrederickCheung 属性中的类(具有自己的属性)没有正确序列化。如果您查看提供的 JSON,您会看到一大堆反斜杠,它们只出现在我自己的对象上,并添加到属性中。但这不是我需要的。我将使给定的 JSON 有效,并提供它需要的外观。然后你就可以看到了。
  • 您的输出看起来好像您在哈希上调用了 to_json,其中值已经是通过调用 to_json 生成的字符串。可能子类的 to_json 实现有问题。
  • @FrederickCheung 所以你说如果我说 orderObject.to_json 它会调用属性类上的 to_json?如果是这样,那将如何运作?我越来越困惑。但我一直在努力去理解它,我一直在运行测试来弄清楚这一点。
  • 这不是我要说的。 Hash 上的 to_json 方法将对所有值调用 to_json,因此它们的实现很重要。

标签: ruby json object


【解决方案1】:

由于您使用了大量元编程,因此作为一个简单的测试,请尝试编写您所期望的实际情况:

def to_json
  hash = {}
  hash["address"] = @address
  hash.to_json
end

从那里,试着找出你的错误在哪里。

编辑:

例如:

class Address
  def to_json(options={})
    {"name" => "foo"}.to_json
  end
end

order_set = OrderSet::OrderObject.new({"address" => Address.new })
order_set.to_json

这就是你所追求的吗?

module JSONable
  def to_json(options={})
    hash = {}
    self.instance_variables.each do |var|
      hash[var[1..-1]] = self.instance_variable_get var
    end
    hash.to_json
  end
end


class Address
  include JSONable
  # Rest of code
end

【讨论】:

  • 我尝试过寻找类和方法。只要我没有嵌套对象,一切都会按计划进行。但是当对象开始播放时......它不起作用......
  • 啊,我明白了,我测试过了。当您在哈希上调用 to_json 时,Address 对象确实需要一个 to_json 方法。Fredrick Cheung 是正确的,这可能是 Address 类 to_json 方法中的一个错误。 JSON.parse 也是一个很好的测试方法。
  • 这是完全相同的 to_json 方法,这就是为什么我的问题还包括让它可能更干燥一点,制作一个主类并将 to_json 移到那里,这样就更少了代码无处不在。
  • 明白了。我个人不会干掉它,直到我有 3 个你知道需要相同行为的对象(无论你是通过模块还是继承来完成)。每个对象都有自己的 to_json 实现,都有它的优点/缺点。它促进鸭子类型并且您信任您的对象。为了干燥而推迟干燥由您决定。
  • i've got 4 modules, containing around 20 classes in total 在我的开篇文章中,他们都使用相同的代码,所以这就是我想要 DRY 的原因(双关语)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-20
  • 2020-08-16
  • 1970-01-01
  • 2015-08-06
  • 2020-09-25
  • 2011-04-27
相关资源
最近更新 更多