HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Deserializer in ruby

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
deserializerrubystackoverflow

Problem

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  0 then
        val = stack.pop
        key = stack.pop
        stack.push({key => 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}")

Solution

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 > 0
          val = stack.pop
          key = stack.pop
          stack.push({key => val})
        end  
        curr_string = ''

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

Code Snippets

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 > 0
          val = stack.pop
          key = stack.pop
          stack.push({key => val})
        end  
        curr_string = ''

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

Context

StackExchange Code Review Q#149731, answer score: 2

Revisions (0)

No revisions yet.