Mikhail Chuprynski
Mikhail Chuprynski

Reputation: 2493

String to Hash of Hashes/Arrays

I have this string which I need to convert to to a Hash :

str = '{:gender=>{:content=>"male"}, :names=>[{:first=>"Atair", :last=>"Goron"}], :addresses=>[{:country=>"GB", :state=>"ENG", :city=>"London"}], :emails=>[{:address=>"[email protected]", :address_md5=>"971b2fd0b83c900a5ca62c91dab80dd9"}, {:address=>"[email protected]", :address_md5=>"a0d958c1396300a344356d57b6836f9e"}], :jobs=>[{:title=>"Chief Executive Officer", :organization=>"Kolis UK and Eire"}, {:title=>"Deputy Managing Director", :organization=>"Kolis UK", :date_range=>{:start=>"2008-04-01", :end=>"2010-04-01"}}, {:title=>"Project Director", :organization=>"Keolis UK", :date_range=>{:start=>"2004-04-01", :end=>"2008-04-01"}}, {:title=>"Strategic Planning Director", :organization=>"Eurostar", :date_range=>{:start=>"2002-04-01", :end=>"2004-04-01"}}, {:title=>"Commercial Director, Business Markets", :organization=>"Eurostar", :date_range=>{:start=>"1999-11-01", :end=>"2002-04-01"}}, {:title=>"Brand Manager", :organization=>"Eurostar", :date_range=>{:start=>"1998-06-01", :end=>"1999-11-01"}}, {:title=>"Business Forecasting Manager", :organization=>"Eurostar", :date_range=>{:start=>"1997-08-01", :end=>"1998-06-01"}}, {:title=>"Principal Consultant", :organization=>"Steer Davies Gleave", :date_range=>{:start=>"1995-04-01", :end=>"1997-08-01"}}, {:title=>"Transport Consultant", :organization=>"Sir Alexander Gibb and Part", :date_range=>{:start=>"1990-01-01", :end=>"1995-12-31"}}], :educations=>[{:school=>"U. of London"}, {:school=>"University College London, U. of London", :date_range=>{:start=>"1987-01-01", :end=>"1990-12-31"}}], :usernames=>[{:content=>"alistair.gordon.75"}], :user_ids=>[{:content=>"5/238/746@linkedin"}, {:content=>"538818605@facebook"}, {:content=>"15504678@linkedin"}]}'

I have floating number of keys, each key value can be either a string, array, hash or hash of hashes

Is there way to convert it?

Upvotes: 2

Views: 120

Answers (2)

Gagan Gami
Gagan Gami

Reputation: 10251

This is dirty way eval : eval Evaluates the Ruby expression(s) in string.

 > s = '{:gender=>{:content=>"male"}, :names=>[{:first=>"Atair", :last=>"Goron"}], :addresses=>[{:country=>"GB", :state=>"ENG", :city=>"London"}], :emails=>[{:address=>"[email protected]", :address_md5=>"971b2fd0b83c900a5ca62c91dab80dd9"}, {:address=>"[email protected]", :address_md5=>"a0d958c1396300a344356d57b6836f9e"}], :jobs=>[{:title=>"Chief Executive Officer", :organization=>"Kolis UK and Eire"}, {:title=>"Deputy Managing Director", :organization=>"Kolis UK", :date_range=>{:start=>"2008-04-01", :end=>"2010-04-01"}}, {:title=>"Project Director", :organization=>"Keolis UK", :date_range=>{:start=>"2004-04-01", :end=>"2008-04-01"}}, {:title=>"Strategic Planning Director", :organization=>"Eurostar", :date_range=>{:start=>"2002-04-01", :end=>"2004-04-01"}}, {:title=>"Commercial Director, Business Markets", :organization=>"Eurostar", :date_range=>{:start=>"1999-11-01", :end=>"2002-04-01"}}, {:title=>"Brand Manager", :organization=>"Eurostar", :date_range=>{:start=>"1998-06-01", :end=>"1999-11-01"}}, {:title=>"Business Forecasting Manager", :organization=>"Eurostar", :date_range=>{:start=>"1997-08-01", :end=>"1998-06-01"}}, {:title=>"Principal Consultant", :organization=>"Steer Davies Gleave", :date_range=>{:start=>"1995-04-01", :end=>"1997-08-01"}}, {:title=>"Transport Consultant", :organization=>"Sir Alexander Gibb and Part", :date_range=>{:start=>"1990-01-01", :end=>"1995-12-31"}}], :educations=>[{:school=>"U. of London"}, {:school=>"University College London, U. of London", :date_range=>{:start=>"1987-01-01", :end=>"1990-12-31"}}], :usernames=>[{:content=>"alistair.gordon.75"}], :user_ids=>[{:content=>"5/238/746@linkedin"}, {:content=>"538818605@facebook"}, {:content=>"15504678@linkedin"}]}'
 > eval(s)
 #=> {:gender=>{:content=>"male"}, :names=>[{:first=>"Atair", :last=>"Goron"}], :addresses=>[{:country=>"GB", :state=>"ENG", :city=>"London"}], :emails=>[{:address=>"[email protected]", :address_md5=>"971b2fd0b83c900a5ca62c91dab80dd9"}, {:address=>"[email protected]", :address_md5=>"a0d958c1396300a344356d57b6836f9e"}], :jobs=>[{:title=>"Chief Executive Officer", :organization=>"Kolis UK and Eire"}, {:title=>"Deputy Managing Director", :organization=>"Kolis UK", :date_range=>{:start=>"2008-04-01", :end=>"2010-04-01"}}, {:title=>"Project Director", :organization=>"Keolis UK", :date_range=>{:start=>"2004-04-01", :end=>"2008-04-01"}}, {:title=>"Strategic Planning Director", :organization=>"Eurostar", :date_range=>{:start=>"2002-04-01", :end=>"2004-04-01"}}, {:title=>"Commercial Director, Business Markets", :organization=>"Eurostar", :date_range=>{:start=>"1999-11-01", :end=>"2002-04-01"}}, {:title=>"Brand Manager", :organization=>"Eurostar", :date_range=>{:start=>"1998-06-01", :end=>"1999-11-01"}}, {:title=>"Business Forecasting Manager", :organization=>"Eurostar", :date_range=>{:start=>"1997-08-01", :end=>"1998-06-01"}}, {:title=>"Principal Consultant", :organization=>"Steer Davies Gleave", :date_range=>{:start=>"1995-04-01", :end=>"1997-08-01"}}, {:title=>"Transport Consultant", :organization=>"Sir Alexander Gibb and Part", :date_range=>{:start=>"1990-01-01", :end=>"1995-12-31"}}], :educations=>[{:school=>"U. of London"}, {:school=>"University College London, U. of London", :date_range=>{:start=>"1987-01-01", :end=>"1990-12-31"}}], :usernames=>[{:content=>"alistair.gordon.75"}], :user_ids=>[{:content=>"5/238/746@linkedin"}, {:content=>"538818605@facebook"}, {:content=>"15504678@linkedin"}]} 

DEMO

Note: as Drenmi commented I also agree with There are some security implications with using eval if possible avoid use of eval . I suggest if possible retrieved response in json instead of string. It executes whatever it is passed, you must be 110% sure (as in, at least no user input anywhere along the way) it would contain only properly formed hashes or unexpected bugs/horrible creatures from outer space might start popping up.

Upvotes: 5

Stefan
Stefan

Reputation: 114138

You could try to convert the format to JSON by replacing :key=> with "key"::

str.gsub!(/:(\w+)=>/, '"\1":')
#=> "{\"gender\":{\"content\":\"male\"}, \"names\":[{\"first\":\"Atair\", ...

And parse it as usual:

require 'json'
JSON.parse(str, symbolize_names: true)
#=> {:gender=>{:content=>"male"}, :names=>[{:first=>"Atair", ...

Upvotes: 11

Related Questions