web-dev-qa-db-ja.com

Ruby JSON解析変更ハッシュキー

このハッシュがあるとしましょう:

{
  :info => [
    {
        :from => "Ryan Bates",
        :message => "sup bra",
        :time => "04:35 AM"
    }
  ]
}

hash[:info]を実行して情報配列を呼び出すことができます。

これをJSON(JSON.generate)に変換してから解析(JSON.parse)すると、次のハッシュが得られます。

{
  "info" => [
    {
        "from" => "Ryan Bates",
        "message" => "sup bra",
        "time" => "04:35 AM"
    }
  ]
}

hash[:info]を使用する場合はnilを返しますが、hash["info"]を使用する場合は返しません。

どうしてこれなの?そして、とにかくこの非互換性を修正する必要はありますか(最初から文字列キーを使用する以外に)?

要するに、いいえ。このように考えてください。JSONでシンボルを保存することは、JSONで文字列を保存することと同じです。そのため、JSON文字列の解析に関しては、2つを区別することはできません。もちろん、文字列キーを再びシンボルに変換したり、実際にクラスを作成してJSONとやり取りすることができますが、これは自動的に行われますが、文字列を使用することをお勧めします。

しかし、それのためだけに、以前に尋ねられたときのこの質問への答えがあります:

json形式のキーと値のペアをRubyシンボルをキーとするハッシュ?)に変換する最良の方法は何ですか?

ActiveSupport :: JSONデコードハッシュシンボルを失う

または、おそらく HashWithIndifferentAccess

21
Lee Jarvis

JSONは記号をサポートしていないため、JSONジェネレーターは記号を文字列に変換します。 JSONキーはすべて文字列であるため、JSONドキュメントを解析すると、デフォルトで文字列キーを含むRubyハッシュが生成されます。

symbolize_namesオプションを使用すると、文字列ではなくシンボルを使用するようにパーサーに指示できます。

例:

original_hash = {:info => [{:from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM"}]}
serialized = JSON.generate(original_hash)
new_hash = JSON.parse(serialized, {:symbolize_names => true})

new_hash[:info]
 #=> [{:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}]

リファレンス: http://www.Ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-parse

134
wyattisimo

With_indifferent_accessメソッドを呼び出すことで同様の問題を解決しました

ここにjson文字列があり、変数sに割り当てることができます

s = "{\"foo\":{\"bar\":\"cool\"}}"

これで、JSONクラスを使用してデータを解析し、hに割り当てることができます

h = JSON.parse(s).with_indifferent_access

これにより、キーとして文字列または記号を受け入れることができるハッシュが生成されます

h[:foo]["bar"]
  #=> "cool"
5
aaron.v
  1. ActiveSupport :: JSON.decodeを使用すると、jsonパーサーを簡単に交換できます
  2. ActiveSupport :: JSON.decode(my_json、symbolize_names:true)を使用します

これにより、ハッシュ内のすべてのキーが再帰的にシンボル化されます。

(Ruby 2.0)で確認済み)

3
Jdfreefly

ハッシュ内のすべてのキーを変更して、文字列から記号に変換することができます。

symbol_hash = Hash[obj.map{ |k,v| [k.to_sym, v] }]

puts symbol_hash[:info]
# => {"from"=>"Ryan Bates", "message"=>"sup bra", "time"=>"04:35 AM"}

残念ながら、配列内にネストされたハッシュでは機能しません。ただし、すべてのハッシュキーを変換する少し再帰的なメソッドを作成できます。

def symbolize_keys(obj)
  #puts obj.class # Useful for debugging
  return obj.collect { |a| symbolize_keys(a) } if obj.is_a?(Array)
  return obj unless obj.is_a?(Hash)
  return Hash[obj.map{ |k,v| [k.to_sym, symbolize_keys(v)] }]
end

symbol_hash = symbolize_keys(hash)
puts symbol_hash[:info]
# => {:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}
2
Kathryn

このようなオプションは使用できません

ActiveSupport::JSON.decode(str_json, symbolize_names: true)

In Rails 4.1以降、ActiveSupport::JSON.decodeは、MultiJSONのオプションハッシュを受け入れなくなりました。 MultiJSONは廃止され、削除されました。

symbolize_keys を使用して処理できます。

ActiveSupport::JSON.decode(str_json).symbolize_keys
0
rails_id