> The "eval" does seem a bit dangerous though.

Especially if you take it a bit to the edge like this (plug into the
other solution):

    RXE = /
        [\[\]\{\}[:space:][:cntrl:]truefals]+|
        (:)|
        (?:,(?>\s*)(?![}\]]))|
        ("(?>[^"\\]+|\\(?:u[0-9a-fA-F]{4}|[bfnrt"\/\\]))*")|
        -?(?=\d)(?>0|[1-9]\d*)(?>\.\d+)?(?>[Ee][+-]?\d+)?(?=\D|$)|
        (null)|
        (.+)
    /xmu

    def parse(json)
        ruby = json.gsub(RXE) do |t|
            if !$4.nil?         then invalid($4)
            elsif !$3.nil?      then 'nil'
            elsif !$1.nil?      then '=>'
            elsif !$2.nil?      then $2.gsub(/#/, '\\\\#')
            else
                t
            end
        end
        begin
            return eval(ruby)
        rescue Exception => e
            invalid(json)
        end
    end

This works because the "null" token does not *start* with any letter
in "true" or "false".  "fnull" would be happily converted to "fnil",
but eval catches that luckily.

As ugly as it is, it cranks in 200kb/sec on my machine, which should
be more than 400kb/sec on yours.  25-30% of C speed is quite
impressive (I had to say this since I was bitching about Ruby's speed
last week...).

Paolo