Вопрос по json, ruby – Доступ к хешам и массивам Ruby

2

В моем приложении на Rails я посылаю сложную строку JSON, которую нужно декодировать. Это не проблема, которую я знаю как.

Теперь, прежде чем я реализую все, что я пытаюсь получить доступ к некоторым примерным структурам JSON, чтобы посмотреть, смогу ли я добраться до всех переменных. Проблема в том, что имена могут быть переменными.

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

        ] }
] } ] } 
</code>

Хорошо, теперь следующие поляare variable: "drinks", "hot", "cold", Все остальные поля будут называться одинаково.

Теперь я хотел бы получить доступ к каждой переменной в этой строке JSON после того, как я ее расшифровал. Перед реализацией я попробовал простой JSON:

<code>{"configuration" : [ { "drinks" : [ { "id":15, "unit":"0.33" } ] } ] }
</code>

После декодирования в рельсах, что приводит к

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

Теперь, как я могу получить доступ к примеруid а такжеunit без использования слова «напитки». Решение также должно быть масштабируемым до приведенного выше примера.

Некоторая дополнительная информация: В большом JSON я должен получить доступ ко всем перечисленным там элементам (идентификаторам), сохранить их в таблице и вернуть новый идентификатор, а затем вставить его обратно в JSON. (объяснение, почему это нужно сделать, займет дополнительную страницу или 4 ^^).

Ваш Ответ

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
Error: User Rate Limit Exceeded DanFritz
Error: User Rate Limit Exceeded DanFritz
1

every terminal has a configuration ("drinks") and can have multiple sub menu's ("hot", "cold") who all have up to 24 items (the "id" and so on)

но JSON, который вы опубликовали в качестве примера, похоже, отражает другую структуру, которая, я думаю, делает вашу задачу излишне сложной. Если JSON предпочтительнее будет сгруппировать иерархически так, как вы описали в своем комментарии, ваша задача станет действительно простой. Похоже, у вас есть возможность изменить сгенерированный JSON, поэтому я рекомендую вам перестроить его иерархию вместо того, чтобы пытаться писать трудный для понимания / поддержки код, который имеет дело со структурой данных, которая вначале не была идеальной ,

В качестве примера вы говорите, что терминал подразумевает его конфигурацию и меню, поэтому я бы поставил терминалы на верхний уровень вместо конфигураций, то есть сделал бы конфигурацию и меню элементом терминала, а не наоборот. Таким образом, вы можете просто перебирать все терминалы, получая доступ к его меню, идентификаторам и т. Д., Не зная, что этот конкретный терминал обслуживает «напитки». например.

Error: User Rate Limit Exceeded DanFritz
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded DanFritz
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]

Это возвращает идентификаторы, но уродливо и теряет всю информацию, откуда пришел идентификатор. Не видя больше вашего кода, я не знаю, достаточно ли этого или нет (вероятно, это не так).

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded DanFritz

Похожие вопросы