Ruby JSON Analysis Changes Hash Keys
Suppose I have this hash:
{ :info => [ { :from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM" } ] } I can call the information array by executing hash[:info] .
Now when I turn this into JSON (JSON.generate) and then parse it (JSON.parse), I get this hash:
{ "info" => [ { "from" => "Ryan Bates", "message" => "sup bra", "time" => "04:35 AM" } ] } Now, if I use hash[:info] , it returns nil , but not if I use hash["info"] .
Why is this? And still, to fix this incompatibility (besides using string keys from the very beginning)?
In short, no. Think of it this way, storing characters in JSON is the same as storing strings in JSON. So you cannot distinguish between the two when it comes to parsing a JSON string. You can, of course, convert string keys back to characters, or actually even build a class for interacting with JSON that does this automatically, but I would recommend just using strings.
But, just for the sake of it, here are the answers to this question in previous times: "/ p>
What is the best way to convert a pair of json-formatted key values ββinto a ruby ββhash with a character as a key?
ActiveSupport :: JSON decodes a hash, losing characters
Or maybe HashWithIndifferentAccess
The JSON generator converts characters to strings because JSON does not support characters. Because JSON keys are all strings, parsing a JSON document by default creates a Ruby hash file with string keys.
You can tell the parser to use characters instead of strings using the symbolize_names parameter.
Example:
original_hash = {:info => [{:from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM"}]} serialized = JSON.generate(original_hash) new_hash = JSON.parse(serialized, {:symbolize_names => true}) new_hash[:info] #=> [{:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}] Link: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-parse
I solved my similar problem with calling the with_indifferent_access method on it
Here I have a json string and we can assign it to the s variable
s = "{\"foo\":{\"bar\":\"cool\"}}" So now I can parse the data with the JSON class and assign it to h
h = JSON.parse(s).with_indifferent_access This will create a hash that can take a string or character as a key
h[:foo]["bar"] #=> "cool" - Use ActiveSupport :: JSON.decode, this will make it easier to change json parsers
- Use ActiveSupport :: JSON.decode (my_json, symbolize_names: true)
This will recursively symbolize all keys in the hash.
(confirmed on ruby ββ2.0)
You can change all the keys in the hash to convert them from string to character:
symbol_hash = Hash[obj.map{ |k,v| [k.to_sym, v] }] puts symbol_hash[:info] # => {"from"=>"Ryan Bates", "message"=>"sup bra", "time"=>"04:35 AM"} Unfortunately, this does not work for a hash nested inside an array. You can, however, write a small recursive method that converts all hash keys:
def symbolize_keys(obj) #puts obj.class # Useful for debugging return obj.collect { |a| symbolize_keys(a) } if obj.is_a?(Array) return obj unless obj.is_a?(Hash) return Hash[obj.map{ |k,v| [k.to_sym, symbolize_keys(v)] }] end symbol_hash = symbolize_keys(hash) puts symbol_hash[:info] # => {:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"} You cannot use this parameter like this
ActiveSupport::JSON.decode(str_json, symbolize_names: true)
In Rails 4.1 or later,
ActiveSupport::JSON.decodeno longer accepts a parameter hash for MultiJSON. MultiJSON has reached its end of life and has been deleted.
You can use symbolize_keys to process it.
ActiveSupport::JSON.decode(str_json).symbolize_keys