Pytanie w sprawie symbol, json, ruby – Dostęp do skrótów i tablic Ruby

2

W mojej aplikacji Rails wysyłam złożony ciąg JSON, który musi zostać zdekodowany. To nie jest problem, który wiem jak.

Teraz, zanim zaimplementuję wszystko, próbuję uzyskać dostęp do niektórych przykładowych struktur JSON, aby sprawdzić, czy mogę dostać się do wszystkich zmiennych. Problem polega na tym, że nazwy mogą być zmienne.

<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>

Ok, teraz następujące polasą zmienne: „napoje”, „gorące”, „zimne”. Wszystkie pozostałe pola będą nazywane tym samym.

Teraz chciałbym uzyskać dostęp do każdej zmiennej w tym łańcuchu JSON po jej zdekodowaniu. Przed wdrożeniem wypróbowałem prosty JSON:

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

Po dekodowaniu w szynach skutkującym

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

Teraz, jak mogę uzyskać dostęp na przykładid iunit bez użycia słowa „napoje”. Rozwiązanie powinno być również skalowalne do powyższego przykładu.

Dodatkowe informacje: W dużym JSON powinienem uzyskać dostęp do wszystkich wymienionych tam przedmiotów (identyfikatorów), zapisać je w tabeli i zwrócić nowy identyfikator, a następnie wstawić z powrotem do JSON. (wyjaśniając, dlaczego należy to zrobić, zajmie dodatkową stronę lub 4 ^^).

Twoja odpowiedź

3   odpowiedź
1

Podsumowując, wydaje się nieco dziwne mieć hash, ale potem nie interesować się kluczami, ale kim jestem, aby osądzić, możesz uzyskać te dziwne dane z innego miejsca lub czegoś.

Biorąc pod uwagę powyższy uproszczony przykład, możesz to zrobić:

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

Teraz spójrzmy na bardziej skomplikowany przykład:

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

Zwraca to identyfikatory, ale jest brzydkie i traci wszystkie informacje, z których pochodzi identyfikator. Nie widząc więcej twojego kodu, nie wiem, czy to wystarczy, czy nie (prawdopodobnie nie jest).

Dzięki, czy możliwe jest również, aby nie utracić wszystkich informacji, skąd pochodzi identyfikator, jak powiedziałeś? To więcej niż potrzeba do powtórzenia powyższego skrótu. Ten skrót jest również tworzony na podstawie złożonej formy w jQuery. Krótki: są przedmioty, terminale i konfiguracje. każdy terminal ma konfigurację („napoje”) i może mieć wiele podmenu („gorące”, „zimne”), które mają do 24 pozycji („identyfikator” itd.). To dlatego jest tak skomplikowane ^^ DanFritz
Jeśli hash jest własny, sprawienie, że będzie mniej skomplikowane, zależy od ciebie (zobacz na przykład odpowiedź @emboss) ;-) Michael Kohl
3

napisałem to, aby zrobić głębokie poszukiwanie w haszu, ale najpierw coś jest nie tak z twoim jsonem, boję się, kiedy go przeanalizujesz, dostaniesz to, zauważysz, że np. terminale nie pokazują wszystkich kluczy. Kod nadal musi zostać dostosowany, aby zwrócić tablicę lub samą tablicę asocjacyjną.

<code>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"}}]}]}]}
</code>

Oto kod

<code>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
</code>

daje

<code>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
</code>

i

<code>hash.dseek("id")
</code>

daje

<code>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
</code>
Dzięki, zmieniłem JSON, więc teraz terminale są tablicą identyfikatorów. Czy to zadziała? DanFritz
Tak, dziękuję, DanFritz
1

W swoim komentarzu, mówisz

każdy terminal ma konfigurację („napoje”) i może mieć wiele podmenu („gorące”, „zimne”), które mają do 24 pozycji („identyfikator” itd.)

ale JSON, który zamieściłeś jako przykład, wydaje się odzwierciedlać inną strukturę, dlatego myślę, że twoje zadanie jest niepotrzebnie trudne. Gdyby JSON był raczej zgrupowany hierarchicznie w sposób opisany w komentarzu, twoje zadanie stałoby się naprawdę łatwe. Wygląda na to, że masz możliwość zmiany wygenerowanego JSON, więc zalecam przeprojektowanie jego hierarchii, zamiast próbować pisać ciężko, aby zrozumieć / utrzymać kod, który zajmuje się strukturą danych, która nie była idealna w pierwszej kolejności .

Jako przykład mówisz, że terminal implikuje jego konfigurację i menu, więc umieściłbym terminale na najwyższym poziomie zamiast konfiguracji, to znaczy, aby konfiguracja i menu były członkami terminala, a nie odwrotnie. W ten sposób można po prostu iterować po wszystkich terminalach, uzyskując dostęp do ich menu, identyfikatorów itd., Nie wiedząc, że ten konkretny terminal obsługuje na przykład „napoje”.

Tak, zamierzam go używać tak, jak powiedziałeś, po prostu wiele konfiguracji (zdefiniowanych raz), a następnie po prostu połączyć terminale, co oszczędza mi możliwości tworzenia niemożliwych dużych jsonów ^^ DanFritz
Dobrze. Aby uniknąć duplikatów, możesz użyć referencji. Nadal grupowałbyś dane w wygodniejszej hierarchii, ale zamiast jawnego duplikowania danych, użyłbyś klucza „ref”, który wskazuje na identyfikator. Następnie deklarujesz terminal poza hierarchią. Zostanie więc zadeklarowane raz, ale będzie się odwoływać wielokrotnie - pomyśl o kluczach obcych w DB. emboss
Dziękuję, tak, moja pierwsza struktura była taka, ale możliwe jest również, że 5 terminali ma taką samą konfigurację. Oznacza to, że wysyłam 5 razy te same informacje do mojego serwera, ponieważ próbuję zapisać „konfigurację” dla wielu szablonów, co skończyło się na tej złożonej strukturze. DanFritz

Powiązane pytania