0

I have the following hash:

{"description":"Hello","id":"H"}`

If I type the hash in the console, I get:

{:description=>"Hello", :id=>"H"}

I would like it to return the same form mentioned first, using "description" and "id".

Is there a way to change the format in which my hash is returned?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Za_Voucha
  • 13
  • 3
  • 1
    Technically, yes, if you override Hash's methods used for dumping, but it's not encouraged, especially if someone else is using your code and expects the default output. Instead of trying to change it, just understand that the two forms are synonymous. – the Tin Man Apr 14 '20 at 06:48
  • 1
    Are you trying to get a JSON representation of the hash? If so, try `hash.to_json`. (you might have to `require 'json'`) – Stefan Apr 14 '20 at 07:05

3 Answers3

1
hash = {:description=>"HS - Hours", :id=>"HS"}

hash.stringify_keys
=> {"description"=>"HS - Hours", "id"=>"HS"}
1

The method that is used to provide a human-readable representation of an object, is #inspect. This is also the method used by most REPLs to display objects, although some REPLs use other, REPL-specific methods such as #pretty_inspect.

It is very important that all of these methods are for human consumption only. You must not parse their output, you must not use them for serialization, processing, or anything other than looking it them for debugging purposes only.

So, knowing that the method in question is Hash#inspect, you could try overriding the method. Just be very aware that changing the behavior of core methods should never be done in production code. This is an example for this answer only:

module HashPrettyPrintExtension
  def inspect
    '{ ' <<
      map do |k, v|
        k = k.to_s if k.is_a?(Symbol)
        %Q[#{k.inspect}: #{v.inspect}]
      end.join(', ') <<
        ' }'
  end
end

module HashPrettyPrintRefinement
  refine Hash do
    prepend HashPrettyPrintExtension
  end
end

{ "description": "Hello", "id": "H" }
#=> { :description => "Hello", :id => "H" }

using HashPrettyPrintRefinement

{ "description": "Hello", "id": "H" }
#=> { "description": "Hello", "id": "H" }

Note that your proposed output is somewhat restricted. It really only works well for keys which are Symbols and values which are Strings, whereas in Ruby, keys can be any arbitrary object and values can be any arbitrary object.

Also, your proposed output is exactly counter to what the goal of #inspect is, namely provide human-readable debugging output because it is not easily visible that the key is not a string.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
0

You have an Hash with Symbol keys:

h = {"description": "Hello", "id": "H"}

Consider this:

({"description": "Hello", "id": "H"}) == ({"description"=> "Hello", "id"=> "H"})
#=> false

({"description": "Hello", "id": "H"}) == ({description: "Hello", id: "H"})
#=> true

Ruby just removes " when printing:

p ({"description":"Hello","id":"H"})
#=> {:description=>"Hello", :id=>"H"}

If you want to convert keys to String, you could use pure Ruby Hash#transform_keys (or the bang version transform_keys!):

h.transform_keys &:to_s
#=> {"description"=>"Hello", "id"=>"H"}

If a json is what you are looking for, do:

require 'json'

puts h.to_json
#=> {"description":"Hello","id":"H"}

Consider also that:

h.to_json.class #=> String
h.class #=> Hash

iGian
  • 11,023
  • 3
  • 21
  • 36