"sup bra", :time => "04:35 AM" }...">

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)?

+49
json ruby ruby-on-rails hash
Sep 25 '11 at 5:11
source share
6 answers

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

+19
Sep 25 2018-11-11T00:
source share

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

+117
Aug 20 2018-12-12T00:
source share

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" 
+4
Mar 13 '15 at 10:16
source share
  • 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)

+2
Jan 15 '14 at 20:54 on
source share

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"} 
+2
May 05 '17 at 6:29 a.m.
source share

You cannot use this parameter like this

ActiveSupport::JSON.decode(str_json, symbolize_names: true)

In Rails 4.1 or later, ActiveSupport::JSON.decode no 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 
0
May 04 '17 at 3:04 a.m.
source share



All Articles