How do I convert a Ruby hash so that all of its keys are symbols?

后端 未结 15 1803
不思量自难忘°
不思量自难忘° 2020-12-04 19:01

I have a Ruby hash which looks like:

{ \"id\" => \"123\", \"name\" => \"test\" }

I would like to convert it to:

{ :id         


        
15条回答
  •  遥遥无期
    2020-12-04 19:37

    If you happen to be in Rails then you'll have symbolize_keys:

    Return a new hash with all keys converted to symbols, as long as they respond to to_sym.

    and symbolize_keys! which does the same but operates in-place. So, if you're in Rails, you could:

    hash.symbolize_keys!
    

    If you want to recursively symbolize inner hashes then I think you'd have to do it yourself but with something like this:

    def symbolize_keys_deep!(h)
      h.keys.each do |k|
        ks    = k.to_sym
        h[ks] = h.delete k
        symbolize_keys_deep! h[ks] if h[ks].kind_of? Hash
      end
    end
    

    You might want to play with the kind_of? Hash to match your specific circumstances; using respond_to? :keys might make more sense. And if you want to allow for keys that don't understand to_sym, then:

    def symbolize_keys_deep!(h)
      h.keys.each do |k|
        ks    = k.respond_to?(:to_sym) ? k.to_sym : k
        h[ks] = h.delete k # Preserve order even when k == ks
        symbolize_keys_deep! h[ks] if h[ks].kind_of? Hash
      end
    end
    

    Note that h[ks] = h.delete k doesn't change the content of the Hash when k == ks but it will preserve the order when you're using Ruby 1.9+. You could also use the [(key.to_sym rescue key) || key] approach that Rails uses in their symbolize_keys! but I think that's an abuse of the exception handling system.

    The second symbolize_keys_deep! turns this:

    { 'a' => 'b', 'c' => { 'd' => { 'e' => 'f' }, 'g' => 'h' }, ['i'] => 'j' }
    

    into this:

    { :a => 'b', :c => { :d => { :e => 'f' }, :g => 'h' }, ['i'] => 'j' }
    

    You could monkey patch either version of symbolize_keys_deep! into Hash if you really wanted to but I generally stay away from monkey patching unless I have very good reasons to do it.

提交回复
热议问题