访问哈希和数组Ruby

在我的Rails应用程序中,我发送了一个需要解码的复杂JSON字符串。 这不是我知道的问题。

在我实现所有内容之前,我正在尝试访问一些示例JSON结构,以查看是否可以获取所有变量。 问题是名称可以是变量。

{"configurations" : [ { "drinks" : [ {"menus" : [ { "hot" : [ {"id":15,"unit":"0.33", "price":"1", "currency":"Euro", "position": 4}, {"id":15,"unit":"0.33", "price":"1", "currency":"Euro", "position": 6} ] }, { "cold" : [ {"id":15,"unit":"0.33", "price":"1", "currency":"Euro", "position": 4}, {"id":15,"unit":"0.33", "price":"1", "currency":"Euro", "position": 6} ] }, { "terminals" : [ {"id" : 4}, {"id": 6}, {"id": 7} ] }, { "keys" : { "debit" : "on", "credit": "off" } } ] } ] } ] } 

好的,现在以下字段是可变的“饮料”,“热”,“冷” 。 所有其他字段将被称为相同。

现在我想在解码之后访问这个JSON字符串中的每个变量。 在实现之前,我尝试了一个简单的JSON:

 {"configuration" : [ { "drinks" : [ { "id":15, "unit":"0.33" } ] } ] } 

在导轨中解码后导致

 { "configuration" => [{"drinks" => [{"id" => 15, "unit" => "0.33" }]}]} 

现在我如何在不使用“饮料”一词的情况下访问idunit 。 该解决方案还应该可扩展到上面的示例。

一些额外的信息:在大型JSON中,我应该访问那里列出的所有项目(id的)将它们保存到表中并返回新的id,然后将其插入JSON中。 (解释为什么需要这样做需要额外的页面或4 ^^)。

我写这篇文章是为了深入寻找哈希,但是首先你的json有些问题我害怕,当你解析它时你会得到这个,你会注意到例如终端没有显示所有的密钥。 代码仍然需要适应返回数组或散列本身。

 hash = JSON.parse(string) #the string you published => {"configurations"=> [{"drinks"=> [{"menus"=> [{"hot"=> [{"id"=>15, "unit"=>"0.33", "price"=>"1", "currency"=>"Euro", "position"=>4}, {"id"=>15, "unit"=>"0.33", "price"=>"1", "currency"=>"Euro", "position"=>6}]}, {"cold"=> [{"id"=>15, "unit"=>"0.33", "price"=>"1", "currency"=>"Euro", "position"=>4}, {"id"=>15, "unit"=>"0.33", "price"=>"1", "currency"=>"Euro", "position"=>6}]}, {"terminals"=>{"id"=>7}}, {"keys"=>{"debit"=>"on", "credit"=>"off"}}]}]}]} 

这里的代码

 class Hash def dseek(search_key = "", path = "") self.each do|key, value| if value.is_a?(Hash) path += "#{key}." value.dseek(search_key, path) else if value.is_a?(Array) path += "#{key}." value.each do |val| val.dseek(search_key, path) end else puts "#{path}#{key}:#{value}" if search_key === key || search_key === "" end end end end end hash.dseek 

 configurations.drinks.menus.hot.id:15 configurations.drinks.menus.hot.unit:0.33 configurations.drinks.menus.hot.price:1 configurations.drinks.menus.hot.currency:Euro configurations.drinks.menus.hot.position:4 configurations.drinks.menus.hot.id:15 configurations.drinks.menus.hot.unit:0.33 configurations.drinks.menus.hot.price:1 configurations.drinks.menus.hot.currency:Euro configurations.drinks.menus.hot.position:6 configurations.drinks.menus.cold.id:15 configurations.drinks.menus.cold.unit:0.33 configurations.drinks.menus.cold.price:1 configurations.drinks.menus.cold.currency:Euro configurations.drinks.menus.cold.position:4 configurations.drinks.menus.cold.id:15 configurations.drinks.menus.cold.unit:0.33 configurations.drinks.menus.cold.price:1 configurations.drinks.menus.cold.currency:Euro configurations.drinks.menus.cold.position:6 configurations.drinks.menus.terminals.id:7 configurations.drinks.menus.keys.debit:on configurations.drinks.menus.keys.credit:off 

 hash.dseek("id") 

 configurations.drinks.menus.hot.id:15 configurations.drinks.menus.hot.id:15 configurations.drinks.menus.cold.id:15 configurations.drinks.menus.cold.id:15 configurations.drinks.menus.terminals.id:7 

总而言之,有一个哈希似乎有点奇怪,但后来对密钥不感兴趣,但是我要判断谁,你可能会从其他地方或其他地方获得那些奇怪的数据。

鉴于上面的简化示例,您可以这样做:

 h["configuration"].first.values.flatten.first #=> {"id"=>15, "unit"=>"0.33"} 

现在让我们看一下更复杂的例子:

 h["configurations"].map(&:values).flatten.first["menus"].map(&:values).flatten.map { |x| x["id"] }.compact #=> [15, 15, 15, 15, 7] 

这将返回ids,但是很丑陋并且丢失了id来自的所有信息。 没有看到更多的代码,我不知道这是否足够(可能不是)。

在你的评论中,你说

每个终端都有一个配置(“饮料”),并且可以有多个子菜单(“热”,“冷”),这些子菜单最多有24个项目(“id”等等)

但是你发布的JSON似乎反映了一种不同的结构,这让我认为你的任务变得不必要。 如果JSON宁愿按照您在评论中描述的方式按层次结构进行分组,那么您的任务将变得非常简单。 听起来你有可能改变生成的JSON,所以我建议你重新设计它的层次结构,而不是试图编写难以理解/维护的代码来处理一开始并不理想的数据结构。

举个例子,你说终端意味着它的配置和菜单,所以我会把终端放在顶层而不是配置上,也就是说,让配置和菜单成为终端的一员而不是相反。 这样,您可以简单地遍历所有终端,访问其菜单,ID等,而无需知道此特定终端提供“饮料”。