Converting Nested Hash Keys from Camelcase to Snake_Case in Ruby

Converting nested hash keys from CamelCase to snake_case in Ruby

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

Convert hash keys to lowercase -- Ruby Beginner

You can use something like this:

CSV.foreach(file, :headers => true) do |row|
new_hash = {}
row.to_hash.each_pair do |k,v|
new_hash.merge!({k.downcase => v})
end

Users.create!(new_hash)
end

I had no time to test it but, you can take idea of it.

Hope it will help

Automatically convert hash keys to camelCase in JBuilder

As Bryce has mentioned, Jbuilder uses to_json instead of processing the hash.

A simple solution is to use json.set! to manually serialize the hash.

json.key_format! camelize: :lower

json.data_object do
@foo.each do |key, value|
json.set! key, value
end
end

Although, there is an issue: if @foo is empty, it won't create an object at all. These are the solutions I found:

  1. Define an empty hash before the serialization

    json.key_format! camelize: :lower

    json.data_object({}) # don't forget parentheses or Ruby will handle {} as a block

    json.data_object do
    @foo.each do |key, value|
    json.set! key, value
    end
    end
  2. Serialize an empty hash if the source variable is empty

    json.key_format! camelize: :lower

    if (@foo.empty?) do
    json.data_object({})
    else
    json.data_object do
    @foo.each do |key, value|
    json.set! key, value
    end
    end
    end

    Or if you prefer your code flat

    json.key_format! camelize: :lower

    json.data_object({}) if @foo.empty?

    json.data_object do
    @foo.each do |key, value|
    json.set! key, value
    end
    end unless @foo.empty?

However, those solutions will not work if you have to serialize nested objects. You can achieve deep serialization by monkeypatching the json object inside Jbuilder

def json.hash!(name, hash)
if hash.empty?
set! name, {}
else
set! name do
hash.each do |key, value|
if value.is_a?(Hash)
hash! key, value
else
set! key, value
end
end
end
end
end

Then you can simply use json.hash! :data_object, @foo and get the desired result.

Rails - Serialize Model to JSON with camelize

It seems weird to me to use camelized attribute names in Rails, let alone json. I would stick to the conventions and use underscored variable names.

However, have a look at this gem: RABL. It should be able to help you out.

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

hash = {"apple" => "banana", "coconut" => "domino"}
Hash[hash.map{ |k, v| [k.to_sym, v] }]
#=> {:apple=>"banana", :coconut=>"domino"}

@mu is too short: Didn't see word "recursive", but if you insist (along with protection against non-existent to_sym, just want to remind that in Ruby 1.8 1.to_sym == nil, so playing with some key types can be misleading):

hash = {"a" => {"b" => "c"}, "d" => "e", Object.new => "g"}

s2s =
lambda do |h|
Hash === h ?
Hash[
h.map do |k, v|
[k.respond_to?(:to_sym) ? k.to_sym : k, s2s[v]]
end
] : h
end

s2s[hash] #=> {:d=>"e", #<Object:0x100396ee8>=>"g", :a=>{:b=>"c"}}

Converting camel case to underscore case in ruby

Rails' ActiveSupport
adds underscore to the String using the following:

class String
def underscore
self.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
end

Then you can do fun stuff:

"CamelCase".underscore
=> "camel_case"

Iterate over a deeply nested level of hashes in Ruby

If I understand the goal, then you should be able to pass in the parent to your save method. For the top level, it will be nil. The following shows the idea where puts is used as a place holder for the "save".

def save_pair(parent, myHash)
myHash.each {|key, value|
value.is_a?(Hash) ? save_pair(key, value) :
puts("parent=#{parent.nil? ? 'none':parent}, (#{key}, #{value})")
}
end

Here is an example call to it:

hash = Hash.new
hash["key1"] = "value1"
hash["key2"] = "value2"
hash["key3"] = Hash.new
hash["key3"]["key4"] = "value4"
hash["key3"]["key5"] = "value5"
hash["key6"] = Hash.new
hash["key6"]["key7"] = "value7"
hash["key6"]["key8"] = Hash.new
hash["key6"]["key8"]["key9"] = "value9"

save_pair(nil, hash)

How to elegantly rename all keys in a hash in Ruby?

ages = { 'Bruce' => 32, 'Clark' => 28 }
mappings = { 'Bruce' => 'Bruce Wayne', 'Clark' => 'Clark Kent' }

ages.transform_keys(&mappings.method(:[]))
#=> { 'Bruce Wayne' => 32, 'Clark Kent' => 28 }

Parse JSON in Rails app that is camelCase

I found some code here so I post it again for you so it is easy to copy.

def underscore_key(k)
if defined? Rails
k.to_s.underscore.to_sym
else
to_snake_case(k.to_s).to_sym
end
end

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

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

here are some small tests to prove the functionality:

p convert_hash_keys({abc:"x"})          # => {:abc=>"x"}
p convert_hash_keys({abcDef:"x"}) # => {:abc_def=>"x"}
p convert_hash_keys({AbcDef:"x"}) # => {:abc_def=>"x"}
p convert_hash_keys(["abc"]) # => ["abc"]
p convert_hash_keys([abc:"x"]) # => [{:abc=>"x"}]
p convert_hash_keys([abcDef:"x"]) # => [{:abc_def=>"x"}]

I hope that meets your requirements.



Related Topics



Leave a reply



Submit