Ruby 1.9.1 built-in JSON troubles

  • Thread starter Aaron D. Gifford
  • Start date
A

Aaron D. Gifford

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.
 
B

Brian Candler

Aaron said:
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.
 
A

Aaron D. Gifford

Aaron said:
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.
 
A

Aaron D. Gifford

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.
 
B

Brian Candler

Aaron said:
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
 
A

Aaron D. Gifford

... 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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top