2

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

        ] }
] } ] } 

さて、次のフィールドは可変です"drinks"、 "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 ^^が必要です)。

4

3 に答える 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
于 2012-05-05T13:06:46.733 に答える
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がどこから来たのかすべての情報を失います。あなたのコードをもっと見なければ、それで十分かどうかはわかりません(おそらくそうではありません)。

于 2012-05-05T10:02:35.763 に答える
1

あなたのコメントで、あなたは言います

すべての端末には構成(「飲み物」)があり、複数のサブメニュー(「ホット」、「コールド」)を持つことができ、すべてに最大24個のアイテム(「ID」など)があります。

しかし、例として投稿したJSONは別の構造を反映しているようで、タスクが不必要に難しくなっていると思います。コメントで説明したようにJSONを階層的にグループ化する方がよい場合は、タスクが非常に簡単になります。生成されるJSONを変更する可能性があるようです。そのため、そもそも理想的ではなかったデータ構造を処理する、理解しにくい/保守しにくいコードを記述しようとするのではなく、階層を再設計することをお勧めします。 。

例として、ターミナルはその構成とメニューを意味すると言うので、私はターミナルを構成ではなくトップレベルに配置します。つまり、構成とメニューをその逆ではなくターミナルのメンバーにします。このようにして、たとえばこの特定の端末が「飲み物」を提供していることを知らなくても、すべての端末を繰り返し処理して、メニューやIDなどにアクセスできます。

于 2012-05-05T12:31:20.397 に答える