Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decode JSON in rails simple string raises error

I'm trying to roundtrip encode/decode plain strings in json, but I'm getting an error.

In rails 2.3. w/ ruby 1.8.6, it used to work.

>> puts ActiveSupport::JSON.decode("abc".to_json)
abc
=> nil

In rails 3.1beta1 w/ ruby 1.9.2, it raises an error.

ruby-1.9.2-p180 :001 > puts ActiveSupport::JSON.decode("abc".to_json)
MultiJson::DecodeError: 706: unexpected token at '"abc"'
    from /home/stevenh/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/json/common.rb:147:in `parse'
    from /home/stevenh/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/json/common.rb:147:in `parse'
    from /home/stevenh/.rvm/gems/ruby-1.9.2-p180/gems/multi_json-1.0.1/lib/multi_json/engines/json_gem.rb:13:in `decode'
    [...]

This is pretty much the same question discussed at nil.to_json cannot be parsed back to nil?

But nil used to work in 2.3/1.8.7 as well.

puts ActiveSupport::JSON.decode(nil.to_json)
nil

Is this the new normal?

like image 538
mshiltonj Avatar asked May 27 '11 17:05

mshiltonj


2 Answers

This change occurred with the switch from ActiveSupport's JSON backend to MultiJson that was included in Rails 3.1.0.rc1. Per the MultiJson project team, the current behavior is correct and the previous implementation was faulty due to RFC4627's specification of the JSON grammar:

2.  JSON Grammar

   A JSON text is a sequence of tokens.  The set of tokens includes six
   structural characters, strings, numbers, and three literal names.

   A JSON text is a serialized object or array.

      JSON-text = object / array

As neither "abc" nor "/"abc/"" are serialized objects or arrays, an error when attempting to decode them is appropriate.

The diagrams from the JSON website reinforce this specification.

That being said, this would seem to imply a bug in the to_json implementation that results in:

ruby-1.9.2-p180 :001 > "abc".to_json
 => "\"abc\""
like image 132
Yardboy Avatar answered Nov 18 '22 04:11

Yardboy


Yes, what is happening in Rails3 is the new normal. The changes you illustrate seem like a reflection of a maturing framework.

Methods named "encode" & "decode" should be expected to be perfectly compliant with the JSON spec, and inverses of one another.

String#to_json, on the other hand is a behavior-ish type of method that functions as a convenience for building more complex JSON objects presumably used internally (within ActiveSupport) when Array#to_json or Hash#to_json encounter a String value as one of their consituent elements.

like image 1
Joe Goggins Avatar answered Nov 18 '22 02:11

Joe Goggins