Here's my own recursive descent parser (based on the not-quite-correct  
quiz tests):

#!/usr/bin/env ruby -wKU

require "strscan"

# http://json.org/
class JSONParser
   AST = Struct.new(:value)

   def parse(input)
     @input = StringScanner.new(input.strip)
     parse_value.value
   end

   private

   def parse_value
     parse_object  or
     parse_array   or
     parse_string  or
     parse_number  or
     parse_keyword or
     error("Illegal JSON value")
   end

   def parse_object
     if @input.scan(/\{\s*/)
       object = Hash.new
       while key = parse_string
         @input.scan(/\s*:\s*/) or error("Expecting object separator")
         object[key.value] = parse_value.value
         @input.scan(/\s*,\s*/) or break
       end
       @input.scan(/\s*\}\s*/) or error("Unclosed object")
       AST.new(object)
     else
       false
     end
   end

   def parse_array
     if @input.scan(/\[\s*/)
       array = Array.new
       while contents = parse_value rescue nil
         array << contents.value
         @input.scan(/\s*,\s*/) or break
       end
       @input.scan(/\s*\]\s*/) or error("Unclosed array")
       AST.new(array)
     else
       false
     end
   end

   def parse_string
     if @input.scan(/"/)
       string = String.new
       while contents = parse_string_content || parse_string_escape
         string << contents.value
       end
       @input.scan(/"\s*/) or error("Unclosed string")
       AST.new(string)
     else
       false
     end
   end

   def parse_string_content
     @input.scan(/[^\\"]+/) and AST.new(@input.matched)
   end

   def parse_string_escape
     if @input.scan(%r{\\["\\/]})
       AST.new(@input.matched[-1])
     elsif @input.scan(/\\[bfnrt]/)
       AST.new(eval(%Q{"#{@input.matched}"}))
     elsif @input.scan(/\\u[0-9a-fA-F]{4}/)
       AST.new([Integer("0x#{@input.matched[2..-1]}")].pack("U"))
     else
       false
     end
   end

   def parse_number
     @input.scan(/-?(?:0|[1-9]\d*)(?:\.\d+(?:[eE][+-]?\d+)?)?\b/) and
     AST.new(eval(@input.matched))
   end

   def parse_keyword
     @input.scan(/\b(?:true|false|null)\b/) and
     AST.new(eval(@input.matched.sub("null", "nil")))
   end

   def error(message)
     if @input.eos?
       raise "Unexpected end of input."
     else
       raise "#{message}:  #{@input.peek(@input.string.length)}"
     end
   end
end

__END__

James Edward Gray II