Converting nested hash keys from CamelCase to snake_case in Ruby

后端 未结 6 435
一生所求
一生所求 2020-12-30 20:21

I\'m trying to build an API wrapper gem, and having issues with converting hash keys to a more Rubyish format from the JSON the API returns.

The JSON contains multip

相关标签:
6条回答
  • 2020-12-30 20:53

    If you use Rails:

    Example with hash: camelCase to snake_case:

    hash = { camelCase: 'value1', changeMe: 'value2' }
    
    hash.transform_keys { |key| key.to_s.underscore }
    # => { "camel_case" => "value1", "change_me" => "value2" }
    

    source: http://apidock.com/rails/v4.0.2/Hash/transform_keys

    For nested attributes use deep_transform_keys instead of transform_keys, example:

    hash = { camelCase: 'value1', changeMe: { hereToo: { andMe: 'thanks' } } }
    
    hash.deep_transform_keys { |key| key.to_s.underscore }
    # => {"camel_case"=>"value1", "change_me"=>{"here_too"=>{"and_me"=>"thanks"}}}
    

    source: http://apidock.com/rails/v4.2.7/Hash/deep_transform_keys

    0 讨论(0)
  • 2020-12-30 20:53

    Use deep_transform_keys for recursive conversion.

    transform_keys only convert it in high level

    hash = { camelCase: 'value1', changeMe: {nestedMe: 'value2'} }
    
    hash.transform_keys { |key| key.to_s.underscore }
    # => { "camel_case" => "value1", "change_me" => {nestedMe: 'value2'} }
    

    deep_transform_keys will go deeper and transform all nested hashes as well.

    hash = { camelCase: 'value1', changeMe: {nestedMe: 'value2'} }
    
    hash.deep_transform_keys { |key| key.to_s.underscore }
    # => { "camel_case" => "value1", "change_me" => {nested_me: 'value2'} }
    
    0 讨论(0)
  • 2020-12-30 20:58

    If you're using the active_support library, you can use deep_transform_keys! like so:

    hash.deep_transform_keys! do |key|
      k = key.to_s.snakecase rescue key
      k.to_sym rescue key
    end
    
    0 讨论(0)
  • 2020-12-30 21:00

    The accepted answer by 'mu is too short' has been converted into a gem, futurechimp's Plissken:

    https://github.com/futurechimp/plissken/blob/master/lib/plissken/ext/hash/to_snake_keys.rb

    This looks like it should work outside of Rails as the underscore functionality is included.

    0 讨论(0)
  • 2020-12-30 21:04

    You need to treat Array and Hash separately. And, if you're in Rails, you can use underscore instead of your homebrew to_snake_case. First a little helper to reduce the noise:

    def underscore_key(k)
      k.to_s.underscore.to_sym
      # Or, if you're not in Rails:
      # to_snake_case(k.to_s).to_sym
    end
    

    If your Hashes will have keys that aren't Symbols or Strings then you can modify underscore_key appropriately.

    If you have an Array, then you just want to recursively apply convert_hash_keys to each element of the Array; if you have a Hash, you want to fix the keys with underscore_key and apply convert_hash_keys to each of the values; if you have something else then you want to pass it through untouched:

    def convert_hash_keys(value)
      case value
        when Array
          value.map { |v| convert_hash_keys(v) }
          # or `value.map(&method(:convert_hash_keys))`
        when Hash
          Hash[value.map { |k, v| [underscore_key(k), convert_hash_keys(v)] }]
        else
          value
       end
    end
    
    0 讨论(0)
  • 2020-12-30 21:04

    I use this short form:

    hash.transform_keys(&:underscore)
    

    And, as @Shanaka Kuruwita pointed out, to deeply transform all the nested hashes:

    hash.deep_transform_keys(&:underscore)
    
    0 讨论(0)
提交回复
热议问题