このハッシュがあるとしましょう:
{
: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
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
With_indifferent_accessメソッドを呼び出すことで同様の問題を解決しました
ここにjson文字列があり、変数sに割り当てることができます
s = "{\"foo\":{\"bar\":\"cool\"}}"
これで、JSONクラスを使用してデータを解析し、hに割り当てることができます
h = JSON.parse(s).with_indifferent_access
これにより、キーとして文字列または記号を受け入れることができるハッシュが生成されます
h[:foo]["bar"]
#=> "cool"
これにより、ハッシュ内のすべてのキーが再帰的にシンボル化されます。
(Ruby 2.0)で確認済み)
ハッシュ内のすべてのキーを変更して、文字列から記号に変換することができます。
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"}
このようなオプションは使用できません
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