2017-01-21 2 views
0

Мне нужно получить все значения ключей «name» и в то же время получить значения «дочерних» ключей. Я могу получить только «имена» с первого уровня, но застрял с «детьми», так как не все «имена» имеют их.Как я могу получить конкретные значения ключей от json?

puts data['labels'].collect { |item| item['name'] } 

JSON ответ следующее:

{"labels": [{ 
    "name": "Crime" 
}, { 
    "name": "Demonstrations" 
}, { 
    "name": "Music", 
    "children": [{ 
     "name": "Awards" 
    }, { 
     "name": "Classical" 
    }, { 
     "name": "Country" 
    }, { 
     "name": "Other" 
    }, { 
     "name": "Pop" 
    }, { 
     "name": "Soul" 
    }, { 
     "name": "X Factor" 
    }] 
}, { 
    "name": "Politics" 
}, { 
    "name": "Rescue" 
}, { 
    "name": "Special Events" 
}, { 
    "name": "Sports", 
    "children": [{ 
     "name": "Auto Racing" 
    }, { 
     "name": "Awards" 
    }, { 
     "name": "Baseball" 
    }, { 
     "name": "Basketball" 
    }, { 
     "name": "NASCAR (Cup)" 
    }, { 
     "name": "NASCAR (Nationwide)" 
    }, { 
     "name": "NASCAR (Truck)" 
    }, { 
     "name": "NASCAR (XFINITY)" 
    }, { 
     "name": "Other" 
    }, { 
     "name": "Rodeo" 
    }, { 
     "name": "Rugby" 
    }, { 
     "name": "Running" 
    }, { 
     "name": "Sailing" 
    }, { 
     "name": "Skating" 
    }, { 
     "name": "Volleyball" 
    }] 
}, { 
    "name": "Traffic" 
}, { 
    "name": "Weather" 
}]} 

ответ

2
puts data['labels'].collect { |item| item['name'] } 

выдаст ошибку

NoMethodError: undefined method `map' for nil:NilClass 

поскольку ключи являются символами, а не строки.

Также

и в то же время, чтобы получить значения «детей» ключей

Вы уверены, что вы хотите получить ключи? Потому что все ключи идентичны (:name). Может быть, вам нужны ценности? В любом случае, если вам нужны ключи, просто измените values на keys в нижнем решении.

решения Теперь (с помощью безопасного навигатора (&)):

data[:labels].map { |item| [item[:name], item[:children]&.map(&:values)] } 
# => [["Crime", nil], 
#  ["Demonstrations", nil], 
#  ["Music", ["Awards", "Classical", "Country", "Other", "Pop", "Soul", "X Factor"]], 
#  ["Politics", nil], 
#  ["Rescue", nil], 
#  ["Special Events", nil], 
#  ["Sports", ["Auto Racing", "Awards", "Baseball", "Basketball", "NASCAR (Cup)", "NASCAR (Nationwide)", "NASCAR (Truck)", "NASCAR (XFINITY)", "Other", "Rodeo", "Rugby", "Running", "Sailing", "Skating", "Volleyball"]], 
#  ["Traffic", nil], 
#  ["Weather", nil] 
# ] 

выше решение без использования безопасного навигатора:

data[:labels].map { |item| [item[:name], item[:children] ? item[:children].map(&:values) : nil] } 
+0

Andrey, p data ['labels']. Collect {| item | item ['name']} не вызывает ошибки для меня, он просто захватывает значения всех «имя», но игнорирует «имя», которые связаны с «детьми». Я на рубине 2.1.2, и безопасный оператор навигации в моем случае не поддерживается ((( –

+0

@DenisS. Я отредактировал answr –

+0

Спасибо, Андрей! Именно это я и пытался получить! –

1

Если h вашего хэша, вы могли бы написать

h[:labels].map do |f| 
    g = { name: f[:name] } 
    f.key?(:children) ? g.merge(children: f[:children].flat_map(&:values)) : g 
end 
    #=> [{:name=>"Crime"}, 
    # {:name=>"Demonstrations"}, 
    # {:name=>"Music", 
    #  :children=>["Awards", "Classical", "Country", "Other", "Pop", "Soul", "X Factor"] 
    # }, 
    # {:name=>"Politics"}, 
    # {:name=>"Rescue"}, 
    # {:name=>"Special Events"}, 
    # {:name=>"Sports", 
    #  :children=>["Auto Racing", "Awards", "Baseball", "Basketball", "NASCAR (Cup)", 
    #     "NASCAR (Nationwide)", "NASCAR (Truck)", "NASCAR (XFINITY)", "Other", 
    #     "Rodeo", "Rugby", "Running", "Sailing", "Skating", "Volleyball"] 
    # }, 
    # {:name=>"Traffic"}, 
    # {:name=>"Weather"} 
    # ] 

Используются методы Hash#key?, Hash#merge, Enumerable#flat_map и еще несколько распространенных.

+0

Thanks Cary , но, к сожалению, я на Ruby 2.1.2, и безопасный оператор навигации не поддерживается в моем случае ((( –

+0

Denis, я не использовал безопасного навигатора. Возможно, вы намеревались написать свой комментарий для @Andrey. –

+0

oooops, my плохой Кэри. Ты прав) Я ценю ваш ответ) Спасибо –

Смежные вопросы