matanco
matanco

Reputation: 2129

How to check if a string contain valid hash

i encounter a problem when i want to validate the input string if it contain a valid hash before execute eval on it, for example:

"{:key=>true}" if i run eval it return a correct hash, but if i run eval on this string "{:key=>true" i get syntax error of expected token:

(eval):1: syntax error, unexpected end-of-input, expecting '}' {:redirect=>true ^

i did tried some basic validation but no luck so far.

so basically what i want to know is how to validate a that a string contain correct hash format.

Upvotes: 1

Views: 2690

Answers (3)

Raphael Müller
Raphael Müller

Reputation: 11

I had a similar problem, but I don't like the eval solution, because it's not safe.

I used the JSON gem and modified the string to match the JSON syntax.

Assuming you only have symbol keys.

  1. 'key: value' to '"key": value'
  2. ':key => value' to '"key": value'

string1 = "{:key_1=>true,key_2:false}"
string2 = "{:key=>true}"
string3 = "no hash"

def valid_hash?(string)
  begin
    string = string.gsub(/(\w+):\s*([^},])/, '"\1":\2')
    #=> "{:key_1=>true,\"key_2\":false}"
    string = string.gsub(/:(\w+)\s*=>/, '"\1":')
    #=> "{\"key_1\":true,\"key_2\":false}"
    my_hash = JSON.parse(string, {symbolize_names: true})
    #=> {:key_1=>true, :key_2=>false}
    my_hash.is_a? Hash # or do whatever you want with your Hash
  rescue JSON::ParserError
    false
  end
end

valid_hash? string1
#=> true
valid_hash? string2
#=> true
valid_hash? string3
#=> false

Upvotes: 1

Andrey Deineko
Andrey Deineko

Reputation: 52357

To validate the string you can use Kernel#eval + checking the type:

def valid_hash?(string)
  eval(string).is_a?(Hash)
rescue SyntaxError
  false
end

Usage:

string = "{:key=>true}"
valid_hash?(string)
#=> true
string = "I am not hash"
valid_hash?(string)
#=> false

Upvotes: 2

user229044
user229044

Reputation: 239302

You can't tell without actually parsing it as Ruby, and (assuming you trust the string), the simplest way of parsing it is to simply do the eval call, and handle the exception:

begin
  hash = eval(string)
rescue SyntaxError
  # It's not valid
end

This is precisely what exceptions are for, instead of littering your code with checks for whether operations will succeed, you just perform the operations, and handle errors that occur.

Upvotes: 4

Related Questions