read rails parse example crear ruby-on-rails ruby json

ruby on rails - rails - ¿Cuál es la mejor manera de convertir un par de valores clave formateados json a hash ruby con símbolo como clave?



ruby read json (6)

Leventix, gracias por tu respuesta.

El método Marshal.load (Marshal.dump (h)) probablemente tenga la mayor integridad de los diversos métodos, ya que conserva los tipos de clave originales recursivamente .

Esto es importante en caso de que tenga un hash anidado con una combinación de cadenas y teclas de símbolos y desea conservar esa mezcla en la decodificación (por ejemplo, esto podría suceder si su hash contiene sus propios objetos personalizados además del tercero altamente complejo / anidado) - objetos de partes cuyas claves no se pueden manipular / convertir por cualquier razón, como una restricción de tiempo del proyecto).

P.ej:

h = { :youtube => { :search => ''daffy'', # nested symbol key ''history'' => [''goofy'', ''mickey''] # nested string key } }

Método 1 : JSON.parse: simboliza todas las teclas recursivamente => No conserva la mezcla original

JSON.parse( h.to_json, {:symbolize_names => true} ) => { :youtube => { :search=> "daffy", :history => ["goofy", "mickey"] } }

Método 2 : ActiveSupport :: JSON.decode: simboliza las claves de nivel superior solamente => No conserva la mezcla original

ActiveSupport::JSON.decode( ActiveSupport::JSON.encode(h) ).symbolize_keys => { :youtube => { "search" => "daffy", "history" => ["goofy", "mickey"] } }

Método 3 : Marshal.load - conserva la mezcla original de cadena / símbolo en las claves anidadas. ¡PERFECTO!

Marshal.load( Marshal.dump(h) ) => { :youtube => { :search => "daffy", "history" => ["goofy", "mickey"] } }

A menos que haya un inconveniente que desconozco, creo que el Método 3 es el camino a seguir.

Aclamaciones

Me pregunto cuál es la mejor manera de convertir un par de valores clave formateados json a hash ruby ​​con símbolo como clave: ejemplo:

{ ''user'': { ''name'': ''foo'', ''age'': 40, ''location'': { ''city'' : ''bar'', ''state'': ''ca'' } } } ==> { :user=>{ :name => ''foo'', :age =>''40'', :location=>{ :city => ''bar'', :state=>''ca'' } } }

¿Hay algún método auxiliar que pueda hacer esto?


Método recursivo:

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


No hay nada integrado para hacer el truco, pero no es demasiado difícil escribir el código para hacerlo utilizando la joya JSON. Existe un método symbolize_keys integrado en Rails si lo está usando, pero eso no simboliza las claves recursivamente como usted lo necesita.

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

Como dijo Leventix, la gema JSON solo maneja cadenas de comillas dobles (lo que es técnicamente correcto - JSON debe formatearse con comillas dobles). Este pequeño código lo limpiará antes de intentar analizarlo.


Otra forma de manejar esto es usar la serialización / deserialización YAML, que también conserva el formato de la clave:

YAML.load({test: {''test'' => { '':test'' => 5}}}.to_yaml) => {:test=>{"test"=>{":test"=>5}}}

El beneficio de este enfoque parece ser un formato que se adapta mejor a los servicios REST ...



usando la gema json al analizar la cadena json, puedes pasarla en la opción symbolize_names. Ver aquí: http://flori.github.com/json/doc/index.html (mira en el análisis sintáctico)

p.ej:

>> s ="{/"akey/":/"one/",/"bkey/":/"two/"}" >> JSON.parse(s,:symbolize_names => true) => {:akey=>"one", :bkey=>"two"}