Ruby 1.9.1 built-in JSON troubles

Discussion in 'Ruby' started by Aaron D. Gifford, Mar 6, 2010.

  1. I'm puzzled. On a box running Ruby 1.9.1 I try this:

    user@host:/path$ irb
    irb(main):001:0> require 'json'
    => true
    irb(main):002:0> JSON.parse(JSON.generate('\\'))
    JSON::parserError: 598: unexpected token at '"\\"'
    from /usr/local/lib/ruby/1.9/json/common.rb:122:in `parse'
    from /usr/local/lib/ruby/1.9/json/common.rb:122:in `parse'
    from (irb):2
    from /usr/local/bin/irb:12:in `<main>'
    irb(main):003:0> RUBY_VERSION
    => "1.9.1"
    irb(main):004:0> ^D

    This is the JSON module that came with 1.9--I don't have a JSON gem installed.

    Any ideas where to go looking? A little web searching showed me
    various similar problems, but most were under 1.8.

    Looking for a clue,
    Aaron out.
    Aaron D. Gifford, Mar 6, 2010
    #1
    1. Advertising

  2. Aaron D. Gifford wrote:
    > irb(main):002:0> JSON.parse(JSON.generate('\\'))
    > JSON::parserError: 598: unexpected token at '"\\"'


    This is simply because JSON.parse only parses JSON *objects* and
    *arrays*, not strings or numbers.

    >> JSON.parse('{"foo":"bar"}')

    => {"foo"=>"bar"}
    >> JSON.parse('["foo","bar"]')

    => ["foo", "bar"]
    >> JSON.parse('"bar"')

    JSON::parserError: 574: unexpected token at '"bar"'

    I use the following workaround:

    >> json = JSON.generate('\\')

    => "\"\\\\\""
    >> JSON.parse("[" + json + "]").first

    => "\\"

    HTH,

    Brian.
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Mar 8, 2010
    #2
    1. Advertising

  3. On Mon, Mar 8, 2010 at 5:39 AM, Brian Candler <> wrote:
    > Aaron D. Gifford wrote:
    >> irb(main):002:0> JSON.parse(JSON.generate('\\'))
    >> JSON::parserError: 598: unexpected token at '"\\"'

    >
    > This is simply because JSON.parse only parses JSON *objects* and
    > *arrays*, not strings or numbers.
    >
    >>> JSON.parse('{"foo":"bar"}')

    > => {"foo"=>"bar"}
    >>> JSON.parse('["foo","bar"]')

    > => ["foo", "bar"]
    >>> JSON.parse('"bar"')

    > JSON::parserError: 574: unexpected token at '"bar"'
    >
    > I use the following workaround:
    >
    >>> json = JSON.generate('\\')

    > => "\"\\\\\""
    >>> JSON.parse("[" + json + "]").first

    > => "\\"
    >
    > HTH,
    >
    > Brian.


    Thanks for the note, Brian.

    The JSON documentation does NOT make that clear.

    And that limitation is a terrible limitation. Ugly!

    I ended up rolling my own pure Ruby JSON parser that doesn't have that
    work-around requirement. It looks like I could have avoided that with
    your work-around (even though it's sad that the JSON library requires
    such an ugly kludge).

    Aaron out.
    Aaron D. Gifford, Mar 8, 2010
    #3
  4. As per Brian's suggestion, I used his workaround this way:
    (IMHO, JSON ought to handle this automagically.)

    require 'json'
    def json_parse_kludge(data)
    return JSON.parse('[' + data + ']')[0] if data.is_a?(String) &&
    data[0,1] == '"'
    JSON.parse(data)
    end

    Fixes my issue: json_parse_kludge(JSON.generate('\\'))

    irb(main):001:0> require 'json'
    => true
    irb(main):002:0> def json_parse_kludge(data)
    irb(main):003:1> return JSON.parse('[' + data + ']')[0] if
    data.is_a?(String) && data[0,1] == '"'
    irb(main):004:1> JSON.parse(data)
    irb(main):005:1> end
    => nil
    irb(main):006:0> json_parse_kludge(JSON.generate('//'))
    => "//"
    irb(main):007:0>

    Thanks again, Brian!

    Aaron out.
    Aaron D. Gifford, Mar 8, 2010
    #4
  5. Aaron D. Gifford wrote:
    > Thanks for the note, Brian.
    >
    > The JSON documentation does NOT make that clear.


    I could understand if it only allowed an object at the top level (which
    is what CouchDB requires), but I agree it doesn't make sense to allow
    two types of values but not the other types.

    Your kludge is a bit messy, it won't parse ' "foo"' for example (with a
    leading space). If you are afraid of building an extra string, then how
    about:

    def jparse(str)
    return JSON.parse(str) if str =~ /\A\s*[{\[]/
    JSON.parse("[#{str}]")[0]
    end
    --
    Posted via http://www.ruby-forum.com/.
    Brian Candler, Mar 8, 2010
    #5
  6. On Mon, Mar 8, 2010 at 12:19 PM, Brian Candler <> wrote:
    >... If you are afraid of building an extra string, then how
    > about:
    >
    > def jparse(str)
    > =A0return JSON.parse(str) if str =3D~ /\A\s*[{\[]/
    > =A0JSON.parse("[#{str}]")[0]
    > end


    Definitely more robust, since that will handle numbers too. Thanks

    Aaron out.
    Aaron D. Gifford, Mar 9, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Florian Frank
    Replies:
    0
    Views:
    227
    Florian Frank
    Jun 30, 2009
  2. sajuptpm
    Replies:
    2
    Views:
    316
    sajuptpm
    Dec 28, 2012
  3. Acácio Centeno
    Replies:
    1
    Views:
    241
    dieter
    Feb 15, 2013
  4. Bryan Britten
    Replies:
    9
    Views:
    256
    Bryan Britten
    May 28, 2013
  5. David Karr
    Replies:
    1
    Views:
    153
    David Karr
    Jun 17, 2013
Loading...

Share This Page