Deserializer in ruby Given a serialized hash of any depth in string format, convert it into a hash object.


I want to know if my approach is correct, I am capturing states and storing the results in a stack and generating the hash from the stack. Also, is there a name for this kind of parsing approach?

def deserialize(input)
  h = {}
  l = 0
  stack = []
  curr_string = ""
  while l &lt; input.length do
    case input[l]
    when "{" #state = DICT_START
      curr_string = ""
    when ":" #state =  VALUE_START
      stack.push(curr_string)
      curr_string = ""
    when "}", "," #state = DICT_END
      if curr_string != "" then
        stack.push(curr_string)
      end
      if stack.length &gt; 0 then
        val = stack.pop
        key = stack.pop
        stack.push({key =&gt; val})
      end  
      curr_string = ""
    else
      curr_string+=input[l]
    end
    l+=1
  end
  stack.each {|n| h.merge!(n)}
  h
end

p deserialize("{a:test,b:test1,c:test3}")
p deserialize("{a:{b:test1}}")
p deserialize("{a:{b:{c:test1}}}")
p deserialize("{a:{b:{c:test1}},d:123}")
The name for this type of parsing is called the shunting yard algorithm.

Your code itself seems fine, as long as you don't intend to support strings with curly braces, e.g. deserialize("{a:{b:'{{{{{{{{'}}").  The biggest issue I see is that it's not very ruby-like in the naming or formatting.  I've made brief attempt at cleaning it up a little below.

def deserialize(input)
  hash = {}                 # avoid one letter variable names
  stack = [] 
  curr_string = ''          # use single quotes for uninterpolated strings

  input.chars.each do |c|   # This is a better was to loop through the characters
    case c 
      when '{' 
        curr_string = ''
                            # whitespace makes it easier to read the different cases
      when ':' 
        stack.push(curr_string)
        curr_string = ''

      when '}', ',' 
        stack.push(curr_string) unless curr_string.empty?  # unless is the same as "if not"
                                                           # also use one line statements when the logic is simple
        if stack.length &gt; 0
          val = stack.pop
          key = stack.pop
          stack.push({key =&gt; val})
        end  
        curr_string = ''

      else
        curr_string += c
    end
  end
  stack.each { |n| hash.merge!(n)}
  hash
end