2012-05-05 13 views
2

私のRailsアプリケーションでは、デコードする必要がある複雑なJSON文字列を送信しています。それは私が知っている問題ではない。ハッシュと配列へのアクセスRuby

私がすべてを実装する前に、いくつかの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" } } 

     ] } 
] } ] } 

[OK]を、今、次のフィールドは、変数です:"飲み物"、 "暑い"、 "寒い"。その他のフィールドはすべて同じと呼ばれます。

これをデコードした後、このJSON文字列のすべての変数にアクセスしたいと思います。今、私は言葉「飲み物」を使用せずに例idunitのためにアクセスする方法を

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

その結果、レールにデコードした後

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

:それを実装する前に、私はシンプルなJSONをしようと試みました。ソリューションはまた、上記の例にスケーラブルである必要があります。

追加情報:大きなJSONでは、そこにリストされているすべての項目(ID)にアクセスしてテーブルに保存し、新しいIDを返してからJSONに戻す必要があります。 (これを行う必要がある理由を説明するには余分なページか4 ^^が必要です)。

答えて

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

与える

を与えます
+0

ありがとう、端末はIDの配列です。これは使えますか? – DanFritz

+0

はい、ありがとう、 – 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] 

これはidを返しますが、醜いですし、失いIDがどこから来たのかについての情報あなたのコードをもっと見ることなく、私はそれが十分であるかどうかわかりません(おそらくそうではありません)。すべて最大24の項目(持っているあなたのコメントで

+0

ありがとう、あなたが言ったように、IDがどこから来たのかすべての情報を失うこともありえますか?上記のハッシュを繰り返し処理する必要があります。また、このハッシュは、jQueryの複雑なフォームから自己作成されます。短く:アイテム、端末、設定があります。すべての端末は設定(「ドリンク」)を持ち、最大24項目(「ID」など)を持つ複数のサブメニュー(「ホット」、「コールド」)を持つことができます。それほど複雑な理由^^ – DanFritz

+2

ハッシュが自己作成されている場合は、それほど複雑ではありません(例えば、@emboss答えを参照してください);-) –

1

、あなたはすべての端末が設定(「ドリンク」)を持ち、複数のサブメニューの(「ホット」「コールド」)を持つことができます

を言います"id"など)

しかし、例として投稿したJSONは、別の構造を反映しているようです。これは、あなたの仕事を不必要に難しくしていると思います。あなたのコメントに記述された方法でJSONを階層的にグループ化すると、あなたのタスクは本当に簡単になります。生成されるJSONを変更する可能性があるので、最初は理想的ではなかったデータ構造を扱うコードを理解し維持するのに苦労するのではなく、その階層を再設計することをお勧めします。

例として、端末には設定とメニューが含まれているとします。つまり、端末を設定ではなくトップレベルに置くことになります。すなわち、設定やメニューを端末の代わりに使う円形。このようにして、端末のすべてを繰り返し、メニューやIDなどにアクセスするだけで、この特定の端末が「ドリンク」を提供しているかどうかを知る必要がなくなります。

+0

ありがとうございます、私の最初の構造はこれに似ていましたが、 (おそらく)5つの端末がすべて同じ構成を持っています。つまり、複数のtemrinalsの「構成」を保存しようとしているので、私は同じ情報を私のサーバーに5回送信します。この複雑な構造に終わったのです。 – DanFritz

+1

さて、重複を避けるために、参照を使用することができます。もっと便利な階層でデータをグループ化しますが、明示的にデータを複製するのではなく、IDを指すキー "ref"を使用します。次に、階層外の端末を宣言します。だから、一度だけ宣言されますが、何度も参照されます。つまり、DBの外部キーを考えます。 – emboss

+0

はい、私はあなたが言ったように、複数の構成(一度定義されている)を使用して、端末をリンクするだけで、これは不可能な大きなjsonの^^を作成することから私を節約します – DanFritz

関連する問題