Nicolas
Nicolas

Reputation: 785

Ruby: JSON.parse with escaped backslash

I have a a JSON-encoded Array which looks like this (note: this is in a file, not the contents of a string): ["Company\\","NN","Company\\"]. Is this invalid JSON? It contains an escaped \ character and looks right to me. However:

a = '["Company\\","NN","Company\\"]'
 => "[\"Company\\\",\"NN\",\"Company\\\"]" 
JSON.parse a
JSON::ParserError: 387: unexpected token at 'NN","Company\"]'
from /Users/nneubauer/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/json/common.rb:148:in `parse'
from /Users/nneubauer/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/json/common.rb:148:in `parse'
from (irb):11
from /Users/nneubauer/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'

Interestingly:

puts a
["Company\","NN","Company\"]

What am I doing wrong?

Upvotes: 2

Views: 5270

Answers (1)

dpassage
dpassage

Reputation: 5453

I think there's a difference between reading that sequence of bytes from a file, and putting it in your Ruby code literally.

When you use ' as the string delimiter in Ruby code, it still interprets \\ as an escape sequence. So you get a string with the value of ["Company\","NN","Company\"].

Then the JSON parser gets it. It sees the starting [, and then looks for a string. It interprets the \" sequence as an escape, so the first string it sees has a value of Company\",. It then expects to see a comma - but sees NN instead and throws up:

1.9.3-p194 :009 > a = '["Company\\","NN","Company\\"]'
 => "[\"Company\\\",\"NN\",\"Company\\\"]" 
1.9.3-p194 :010 > puts a
["Company\","NN","Company\"]
 => nil 
1.9.3-p194 :011 > JSON.parse(a)
JSON::ParserError: 387: unexpected token at 'NN","Company\"]'

But if I read that byte sequence from a file using gets, then the value ends up being ["Company\\","NN","Company\\"]. This can be parsed as JSON - the \\ is interpreted by JSON, then it sees the " and closes the first string in the array properly.

1.9.3-p194 :012 > b = gets
["Company\\","NN","Company\\"]
 => "[\"Company\\\\\",\"NN\",\"Company\\\\\"]\n" 
1.9.3-p194 :013 > puts b
["Company\\","NN","Company\\"]
 => nil 
1.9.3-p194 :014 > JSON.parse b
 => ["Company\\", "NN", "Company\\"] 
1.9.3-p194 :015 > JSON.parse(b).length
 => 3 

So, what are you doing wrong? Cutting and pasting from a data file into source code. :)

Upvotes: 5

Related Questions