what is the best way to convert a json formatted key value pair to ruby hash with symbol as key? what is the best way to convert a json formatted key value pair to ruby hash with symbol as key? json json

what is the best way to convert a json formatted key value pair to ruby hash with symbol as key?


using the json gem when parsing the json string you can pass in the symbolize_names option. See here: http://flori.github.com/json/doc/index.html (look under parse)

eg:

>> s ="{\"akey\":\"one\",\"bkey\":\"two\"}">> JSON.parse(s,:symbolize_names => true)=> {:akey=>"one", :bkey=>"two"} 


Leventix, thank you for your answer.

The Marshal.load(Marshal.dump(h)) method probably has the most integrity of the various methods because it preserves the original key types recursively.

This is important in case you have a nested hash with a mix of string and symbol keys and you want to preserve that mix upon decode (for instance, this could happen if your hash contains your own custom objects in addition to highly complex/nested third-party objects whose keys you cannot manipulate/convert for whatever reason, like a project time constraint).

E.g.:

h = {      :youtube => {                    :search   => 'daffy',                 # nested symbol key                    'history' => ['goofy', 'mickey']      # nested string key                  }    }

Method 1: JSON.parse - symbolizes all keys recursively => Does not preserve original mix

JSON.parse( h.to_json, {:symbolize_names => true} )  => { :youtube => { :search=> "daffy", :history => ["goofy", "mickey"] } } 

Method 2: ActiveSupport::JSON.decode - symbolizes top-level keys only => Does not preserve original mix

ActiveSupport::JSON.decode( ActiveSupport::JSON.encode(h) ).symbolize_keys  => { :youtube => { "search" => "daffy", "history" => ["goofy", "mickey"] } }

Method 3: Marshal.load - preserves original string/symbol mix in the nested keys. PERFECT!

Marshal.load( Marshal.dump(h) )  => { :youtube => { :search => "daffy", "history" => ["goofy", "mickey"] } }

Unless there is a drawback that I'm unaware of, I'd think Method 3 is the way to go.

Cheers


There isn't anything built in to do the trick, but it's not too hard to write the code to do it using the JSON gem. There is a symbolize_keys method built into Rails if you're using that, but that doesn't symbolize keys recursively like you need.

require 'json'def json_to_sym_hash(json)  json.gsub!('\'', '"')  parsed = JSON.parse(json)  symbolize_keys(parsed)enddef symbolize_keys(hash)  hash.inject({}){|new_hash, key_value|    key, value = key_value    value = symbolize_keys(value) if value.is_a?(Hash)    new_hash[key.to_sym] = value    new_hash  }end

As Leventix said, the JSON gem only handles double quoted strings (which is technically correct - JSON should be formatted with double quotes). This bit of code will clean that up before trying to parse it.