DanMatlin
DanMatlin

Reputation: 1252

Ruby Hash with integer keys changed to string keys

I create a hash in ruby with integer keys and send it as a JSON response. This JSON is then parsed and the hash is converted back to ruby. The keys are now string literals.

I get it that JSON doesnt support integer keys but I came upon this method which basically parses the hash so that it has symbol keys.

JSON.parse(hash, {:symbolize_names => true})

Is there a similar function for obtaining back the original integer keys

a = {1 => 2}
a.keys
=> [1]
b = JSON.parse(JSON.generate(a))
b.keys
=> ["1"]

My hash is very complicated. The value itself is a hash which is supposed to have integer keys. There are multiple such levels of nesting

Upvotes: 8

Views: 4472

Answers (2)

Ritesh Choudhary
Ritesh Choudhary

Reputation: 782

normal key transformation using built in method by passing required block

hash1 = {'1' => {'2' => 'val2', '3' => 'val3'}} 
p hash1.transform_keys(&:to_i)

{1=>{"2"=>"val2", "3"=>"val3"}}

nested key transformation solution by passing required block

class Hash
  def deep_transform_keys(&block)
    result = {}
    each do |key, value|
      result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
    end
    result
  end
end
hash1 = {'1' => {'2' => 'val2', '3' => 'val3'}} 
p hash1.deep_transform_keys(&:to_i)

{1=>{2=>"val2", 3=>"val3"}}

Upvotes: 2

Martin
Martin

Reputation: 7714

Nothing in JSON as far as I know, but conversion is easy:

json_hash = {"1" => "2" }
integer_hash = Hash[json_hash.map{|k,v|[ k.to_i, v.to_i ]}]
=> {1 => 2}

So, we take all key & value from the initial hash (json_hash), call to_i on them and get them in a new hash (integer_hash).

Even nesting is not blocking. You could do this in a method:

def to_integer_keys(hash)
  keys_values = hash.map do |k,v|
    if(v.kind_of? Hash)
      new_value = to_integer_keys(v) #it's a hash, let's call it again
    else
      new_value = v.to_i #it's a integer, let's convert
    end

    [k.to_i, new_value]
  end

  Hash[keys_values]
end

Upvotes: 7

Related Questions