回答:
json文字列を解析するときにjson gemを使用すると、symbolize_namesオプションで渡すことができます。ここを参照してください:http : //flori.github.com/json/doc/index.html(解析の下を見てください)
例えば:
>> s ="{\"akey\":\"one\",\"bkey\":\"two\"}"
>> JSON.parse(s,:symbolize_names => true)
=> {:akey=>"one", :bkey=>"two"}
:symbolize_keys
ませんでしたか?なぜその名前が変わったのですか?
symbolize_keys
Railsのことです。
Leventix、回答ありがとうございます。
Marshal.load(Marshal.dump(H)) 、それは元のキーの種類を保持するための方法は、おそらく様々な方法のほとんどの整合性を持って再帰的に。
これは、文字列キーとシンボルキーが混在するネストされたハッシュがあり、デコード時にそのミックスを保持したい場合に重要です(たとえば、これには、非常に複雑な/ネストされた3番目に加えて、ハッシュに独自のカスタムオブジェクトが含まれている場合に発生する可能性があります-プロジェクトの時間制約など、なんらかの理由でキーを操作/変換できないパーティオブジェクト。
例えば:
h = {
:youtube => {
:search => 'daffy', # nested symbol key
'history' => ['goofy', 'mickey'] # nested string key
}
}
方法1:JSON.parse-すべてのキーを再帰的に記号化する=>元の組み合わせを保持しない
JSON.parse( h.to_json, {:symbolize_names => true} )
=> { :youtube => { :search=> "daffy", :history => ["goofy", "mickey"] } }
方法2:ActiveSupport :: JSON.decode-トップレベルのキーのみをシンボル化=>元のミックスを保持しない
ActiveSupport::JSON.decode( ActiveSupport::JSON.encode(h) ).symbolize_keys
=> { :youtube => { "search" => "daffy", "history" => ["goofy", "mickey"] } }
方法3:Marshal.load-ネストされたキーの元の文字列/シンボルミックスを保持します。パーフェクト!
Marshal.load( Marshal.dump(h) )
=> { :youtube => { :search => "daffy", "history" => ["goofy", "mickey"] } }
私が気づいていない欠点がない限り、私は方法3が進むべき道だと思います。
乾杯
トリックを実行するために組み込まれているものはありませんが、JSON gemを使用してそれを実行するためのコードを記述することはそれほど難しくありません。symbolize_keys
Railsを使用している場合は、それに組み込まれているメソッドがありますが、これは必要なように再帰的にキーをシンボル化するものではありません。
require 'json'
def json_to_sym_hash(json)
json.gsub!('\'', '"')
parsed = JSON.parse(json)
symbolize_keys(parsed)
end
def symbolize_keys(hash)
hash.inject({}){|new_hash, key_value|
key, value = key_value
value = symbolize_keys(value) if value.is_a?(Hash)
new_hash[key.to_sym] = value
new_hash
}
end
Leventixが言ったように、JSON gemは二重引用符で囲まれた文字列のみを処理します(技術的には正しい-JSONは二重引用符でフォーマットする必要があります)。このコードは、解析する前にクリーンアップします。
再帰的な方法:
require 'json'
def JSON.parse(source, opts = {})
r = JSON.parser.new(source, opts).parse
r = keys_to_symbol(r) if opts[:symbolize_names]
return r
end
def keys_to_symbol(h)
new_hash = {}
h.each do |k,v|
if v.class == String || v.class == Fixnum || v.class == Float
new_hash[k.to_sym] = v
elsif v.class == Hash
new_hash[k.to_sym] = keys_to_symbol(v)
elsif v.class == Array
new_hash[k.to_sym] = keys_to_symbol_array(v)
else
raise ArgumentError, "Type not supported: #{v.class}"
end
end
return new_hash
end
def keys_to_symbol_array(array)
new_array = []
array.each do |i|
if i.class == Hash
new_array << keys_to_symbol(i)
elsif i.class == Array
new_array << keys_to_symbol_array(i)
else
new_array << i
end
end
return new_array
end
これを処理するもう1つの方法は、YAMLシリアル化/逆シリアル化を使用することです。これにより、キーの形式も保持されます。
YAML.load({test: {'test' => { ':test' => 5}}}.to_yaml)
=> {:test=>{"test"=>{":test"=>5}}}
このアプローチの利点は、RESTサービスにより適した形式のようです...
YAML.load
任意のオブジェクト(たとえば、キャッシュ)をシリアル化するためのものです。提案されているYAML.safe_load
ことが正しいことを利用しての問題ですので、数ヶ月そのブログ記事の後に導入されました:github.com/ruby/psych/commit/...
最も便利な方法は、nice_hash gemを使用することです。https://github.com/MarioRuiz/nice_hash
require 'nice_hash'
my_str = "{ 'user': { 'name': 'foo', 'age': 40, 'location': { 'city' : 'bar', 'state': 'ca' } } }"
# on my_hash will have the json as a hash
my_hash = my_str.json
# or you can filter and get what you want
vals = my_str.json(:age, :city)
# even you can access the keys like this:
puts my_hash._user._location._city
puts my_hash.user.location.city
puts my_hash[:user][:location][:city]
http://stackoverflow.com/a/43773159/1297435
をRails 4.1で試してください