2

In my Rails application I'm sending a complex JSON string that needs to get decoded. That's not the problem I know how.

Now before I implement everything I'm trying to access some example JSON structures to see if I can get to all the variables. The problem is that the names can be variable.

{"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" }  }

        ] }
] } ] } 

Ok, now the following fields are variable: "drinks", "hot", "cold". All the other fields will be called the same.

Now I would like to access every variable in this JSON string after I decoded it. Before implementing it, I tryed a simple JSON:

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

After decoding in rails resulting in

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

Now how can I access for example id and unit without using the word "drinks". The solution should also be scalable to the example above.

Some extra information: In the large JSON I should access all the items listed there (the id's) save them to a table and return the new id and then insert it back in the JSON. (explaining why this needs to be done will take an extra page or 4 ^^ ).

4

3 回答 3

3

我写这篇文章是为了在哈希中进行深度搜索,但首先恐怕你的 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
于 2012-05-05T13:06:46.733 回答
1

在你的评论中,你说

每个终端都有一个配置(“drinks”),并且可以有多个子菜单(“hot”、“cold”),它们最多有 24 个项目(“id”等)

但是您作为示例发布的 JSON 似乎反映了不同的结构,我认为这使您的任务变得不必要地困难。如果 JSON 宁愿以您在评论中描述的方式分层分组,您的任务将变得非常容易。听起来您有可能更改生成的 JSON,因此我建议您重新设计其层次结构,而不是尝试编写难以理解/维护的代码来处理最初并不理想的数据结构.

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

于 2012-05-05T12:31:20.397 回答
1

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

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

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]

这会返回 id,但很难看,并且会丢失 id 来自的所有信息。在没有看到更多代码的情况下,我不知道这是否足够(可能不是)。

于 2012-05-05T10:02:35.763 回答