How to parse a string representation of a hash
Solution 1
Guess I never posted my workaround for this... Here it goes,
# strip the hash down
stringy_hash = "account_id=>4444, deposit_id=>3333"
# turn string into hash
Hash[stringy_hash.split(",").collect{|x| x.strip.split("=>")}]
Solution 2
The way suggested in miku's answer is indeed easiest and unsafest.
# DO NOT RUN IT
eval '{:surprise => "#{system \"rm -rf / \"}"}'
# SERIOUSLY, DON'T
Consider using a different string representation of your hashes, e.g. JSON or YAML. It's way more secure and at least equally robust.
Solution 3
With a little replacement, you may use YAML:
require 'yaml'
p YAML.load(
"{:account_id=>4444, :deposit_id=>3333}".gsub(/=>/, ': ')
)
But this works only for this specific, simple string. Depending on your real data you may get problems.
Solution 4
if your string hash is some sort of like this (it can be nested or plain hash)
stringify_hash = "{'account_id'=>4444, 'deposit_id'=>3333, 'nested_key'=>{'key1' => val1, 'key2' => val2, 'key3' => nil}}"
you can convert it into hash like this without using eval which is dangerous
desired_hash = JSON.parse(stringify_hash.gsub("'",'"').gsub('=>',':').gsub('nil','null'))
and for the one you posted where the key is a symbol you can use like this
JSON.parse(string_hash.gsub(':','"').gsub('=>','":'))
Solution 5
The easiest and unsafest would be to just evaluate the string:
>> s = "{:account_id=>4444, :deposit_id=>3333}"
>> h = eval(s)
=> {:account_id=>4444, :deposit_id=>3333}
>> h.class
=> Hash
zoras
Updated on December 16, 2021Comments
-
zoras over 2 years
I have this string and I'm wondering how to convert it to a Hash.
"{:account_id=>4444, :deposit_id=>3333}"
-
yaka over 12 yearstry this: stackoverflow.com/questions/1667630/…
-
-
zoras over 12 yearsI'm getting these in rails post params. Isn't there a safe way to convert string into hash other than eval.
-
zoras over 12 yearsnop these are rails post params so i guess i can't use json or yaml
-
Jan over 12 yearsInteresting. Controllers in Rails usually receive
POST
params as Ruby objects. How come you get them as a string? -
miku over 12 yearsI don't know your setup, but maybe it would be easier to get back a hash in the first place. Otherwise, ruby supports some TAINT levels, see: ruby-doc.org/docs/ProgrammingRuby/html/taint.html
-
Pavling over 12 yearslets hope no one runs that to "see what it will do" :-/
-
Jan over 12 years@Pavling, good point. I've added an appropriate piece of advice.
-
zoras over 12 yearsActually, I'm sending these as custom options for paypal like this
:custom => {:account_id => @account.id, :deposit_id => @deposit.id}
. So, when paypal posts back the IPN the hash is quoted as string in the controller. Is there any other way to send multiple variables with paypal custom options altogether? -
Jan over 12 years@zoras, I guess it's a candidate for a new question with a paypal tag.
-
nurettin over 10 yearsthis takes really long when I run it
-
Matt almost 10 yearsThis will fail to split fields correctly if you have any data that contains a
,
or=>
.{ :text => "Welcome, friends.", delim => "=>" }
-
Luca Spiller over 9 yearsHashes contain 'null' for null objects, where as this contains 'nil', so that would need to be replaced too.
-
volx757 over 8 yearsyeah maybe at least explain what the code you wrote does. i feel like it's v possible someone new to ruby/coding might run it anyway just to see. so for that person: it would delete all of your files.
-
Chris Suszyński about 8 yearsYou should add
--no-preserve-root
to your example to really kick balls! :-P -
Josh over 7 yearsWorked like a charm! I passed mine into
HashWithIndifferentAccess.new
to get a hash like the param hash. -
Michael over 6 yearsdon't forget to add
sudo
beforesystem
-
Hosam Aly over 2 yearsThis would only work with data types that are native to YAML. A regular expression, for example, wouldn't be parseable in this way.