8

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

1
  • 1
    Sure, iterate over the keys, convert them to integers, and set their values to the original string keys' values. Commented Aug 20, 2014 at 12:54

2 Answers 2

7

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
Sign up to request clarification or add additional context in comments.

2 Comments

The problem is 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
Then just do it recursively. Avdi Grimm posted a method that does that for YAML and strings/symbols, it should be trivial to combine that with Martin's answer to suit your needs.
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.