在Ruby中将嵌套的哈希键从CamelCase转换为snake_case

我正在尝试构建一个API包装器gem,并且在从API返回的JSON中将哈希键转换为更多Rubyish格式时遇到问题。

JSON包含多层嵌套,包括哈希和数组。 我想要做的是递归地将所有键转换为snake_case以便于使用。

这是我到目前为止所得到的:

def convert_hash_keys(value) return value if (not value.is_a?(Array) and not value.is_a?(Hash)) result = value.inject({}) do |new, (key, value)| new[to_snake_case(key.to_s).to_sym] = convert_hash_keys(value) new end result end 

上面调用此方法将字符串转换为snake_case:

 def to_snake_case(string) string.gsub(/::/, '/'). gsub(/([AZ]+)([AZ][az])/,'\1_\2'). gsub(/([az\d])([AZ])/,'\1_\2'). tr("-", "_"). downcase end 

理想情况下,结果类似于以下内容:

 hash = {:HashKey => {:NestedHashKey => [{:Key => "value"}]}} convert_hash_keys(hash) # => {:hash_key => {:nested_hash_key => [{:key => "value"}]}} 

我得到的递归是错误的,我试过的这种解决方案的每个版本都没有转换超出第一级的符号,或者过度使用并尝试转换整个哈希值,包括值。

试图在辅助类中解决所有这些,而不是修改实际的Hash和String函数,如果可能的话。

先感谢您。

您需要单独处理Array和Hash。 而且,如果您使用的是Rails,则可以使用underscore而不是自制的to_snake_case 。 首先是帮助减少噪音的小帮手:

 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 

如果您的哈希值具有非符号或字符串的键,则可以适当地修改underscore_key

如果你有一个数组,那么你只想递归地将convert_hash_keys应用于数组的每个元素; 如果你有哈希,你想用underscore_key修复键, convert_hash_keys应用于每个值; 如果你还有其他东西,那么你想要通过它原来:

 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 

如果你使用Rails

使用hash的示例:camelCase到snake_case

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

来源: http : //apidock.com/rails/v4.0.2/Hash/transform_keys

对于嵌套属性,请使用deep_transform_keys而不是transform_keys,例如:

 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"}}} 

来源: http : //apidock.com/rails/v4.2.7/Hash/deep_transform_keys

‘mu太短’所接受的答案已被转换为gem,futurechimp的Plissken:

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

这似乎应该在Rails之外工作,因为包含下划线function。

如果您使用的是active_support库,则可以使用deep_transform_keys! 像这样:

 hash.deep_transform_keys! do |key| k = key.to_s.snakecase rescue key k.to_sym rescue key end