在我的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" } }
] }
] } ] }
好的,现在以下字段是可变的:“drink”,“hot”,“cold”。所有其他字段将被称为相同。
现在我想在解码之后访问此JSON字符串中的每个变量。在实现之前,我尝试了一个简单的JSON:
{"configuration" : [ { "drinks" : [ { "id":15, "unit":"0.33" } ] } ] }
在rails中解码导致
{ "configuration" => [{"drinks" => [{"id" => 15, "unit" => "0.33" }]}]}
现在我如何在不使用“饮料”一词的情况下访问id
和unit
。解决方案也应该可以扩展到上面的例子。
一些额外的信息:在大型JSON中,我应该访问那里列出的所有项目(id的)将它们保存到表中并返回新的id,然后将其插入JSON中。 (解释为什么需要这样做需要额外的页面或4 ^^)。
答案 0 :(得分:3)
我写这篇文章是为了深入挖掘Hash,但是首先你的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
答案 1 :(得分: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来自的所有信息。没有看到更多的代码,我不知道这是否足够(可能不是)。
答案 2 :(得分:1)
在你的评论中,你说
每个终端都有一个配置(“饮料”),并且可以有多个子菜单(“热”,“冷”),所有子菜单最多有24个项目(“id”等等)
但是你发布的JSON似乎反映了一个不同的结构,这让我认为你的任务变得不必要。如果JSON宁愿按照您在评论中描述的方式按层次结构进行分组,那么您的任务将变得非常简单。听起来你有可能改变生成的JSON,所以我建议你重新设计它的层次结构,而不是试图编写难以理解/维护的代码来处理一开始并不理想的数据结构。
作为一个例子,你说一个终端意味着它的配置和菜单,所以我会把终端放在顶层而不是配置上,也就是说,使配置和菜单成为终端的一员而不是另一种方式。这样,您可以简单地遍历所有终端,访问其菜单,ID等,而无需知道此特定终端提供“饮料”。