使用 Ruby 中嵌套的 JSON 键值对从 class 创建新的 instance/object

Creating a new instance/object from a class with nested JSON key value pairs in Ruby

我有一些 JSON 想要转换为对象,但我无法弄清楚如何对数据进行排序并将其传递给 class 的初始化方法。

我已经使用 file.read 将我的 JSON 放入数组中组织的 key/value 对中,但是成本属性嵌套如下

      [
        { "restaurant": "hells kitchen", "cost": { "dine in": 100.00 } },
        { "restaurant": "sals pizza", "cost": { "dine in": 25.50, "takeaway": 20.00, "delivery": 28.50 } },
        { "restaurant": "five guys burgers", "cost": { "dine in": 18.50, "takeaway": 16.50, "delivery": 20.00 } }
      ]

理想情况下,我想分配这些值并让它们作为实例化 class 对象的属性进行访问,就像这个粗略的例子。

class Restaurant

    attr_accessor :name, :type, :cost

    def initialise(json_data)
    
    #something to sort the data here#
    
    end

end 

我想不出将数据添加到属性的好方法,非常感谢任何有关如何检索数据并将其放入初始化方法的建议。

如果我的术语、解释或理解不足,我提前道歉,我对 Ruby 和一般编程还很陌生。

谢谢!

json 是一个哈希数组。

abc = [
        { "restaurant": "hells kitchen", "cost": { "dine in": 100.00 } },
        { "restaurant": "sals pizza", "cost": { "dine in": 25.50, "takeaway": 20.00, "delivery": 28.50 } },
        { "restaurant": "five guys burgers", "cost": { "dine in": 18.50, "takeaway": 16.50, "delivery": 20.00 } }
      ]

irb(main):008:0> abc
=> [{:restaurant=>"hells kitchen", :cost=>{:"dine in"=>100.0}}, {:restaurant=>"sals pizza", :cost=>{:"dine in"=>25.5, :takeaway=>20.0, :delivery=>28.5}}, {:restaurant=>"five guys burgers", :cost=>{:"dine in"=>18.5, :takeaway=>16.5, :delivery=>20.0}}]

因此你可以直接操作它

irb(main):009:0> abc[0]
=> {:restaurant=>"hells kitchen", :cost=>{:"dine in"=>100.0}}

我不知道你到底想做什么,但所有 array methods 都可以直接使用:mapeach、...

在初始化方法中,您可以操作数据并设置 class 变量和方法变量。如果在初始化方法中设置变量,attr_reader 就足够了。

最好把解析代码放在Restaurantclass里面这样:

class Restaurant
  attr_accessor :name, :type, :cost

  def initialize(name, type, cost)
    @name, @type, @cost = name, type, cost  
  end
end

restaurants = json_data.flat_map do |hash|
  name = hash[:restaurant]

  hash[:cost].map do |type, cost|
    Restaurant.new(name, type, cost)
  end
end

# Then you can use:
r = restaurants.first
r.name
r.type
r.cost

根据评论更新:

class Restaurant
  attr_accessor :name, :costs

  def initialize(name, costs)
    @name, @costs = name, costs
  end

  def types
    @costs.keys
  end
end

restaurants = json_data.map do |hash|
  Restaurant.new(hash[:restaurant], hash[:cost])
end

# Then you can use:
r = restaurants.first
types = r.types
type1 = types.first
cost1 = r.costs[type1]