From 7275d2749cb829d89bffe7e6aa87c99084351f6a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 30 Sep 2007 20:57:50 +0000 Subject: Fixed JSON encoding to use quoted keys according to the JSON standard (closes #8762) [choonkat/chuyeow] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7697 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/test/controller/render_test.rb | 6 ++-- activerecord/test/json_serialization_test.rb | 5 ---- activesupport/CHANGELOG | 2 ++ .../lib/active_support/json/encoders/hash.rb | 2 -- activesupport/lib/active_support/json/encoding.rb | 12 -------- activesupport/lib/active_support/json/variable.rb | 2 +- activesupport/test/json/encoding_test.rb | 34 ++++------------------ 7 files changed, 11 insertions(+), 52 deletions(-) diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 3b755eb6a6..23c9613cad 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -209,19 +209,19 @@ class RenderTest < Test::Unit::TestCase def test_do_with_render_json get :render_json_hello_world - assert_equal '{hello: "world"}', @response.body + assert_equal '{"hello": "world"}', @response.body assert_equal 'application/json', @response.content_type end def test_do_with_render_json_with_callback get :render_json_hello_world_with_callback - assert_equal 'alert({hello: "world"})', @response.body + assert_equal 'alert({"hello": "world"})', @response.body assert_equal 'application/json', @response.content_type end def test_do_with_render_symbol_json get :render_symbol_json - assert_equal '{hello: "world"}', @response.body + assert_equal '{"hello": "world"}', @response.body assert_equal 'application/json', @response.content_type end diff --git a/activerecord/test/json_serialization_test.rb b/activerecord/test/json_serialization_test.rb index f4d4f4e1a3..d12e7c42c6 100644 --- a/activerecord/test/json_serialization_test.rb +++ b/activerecord/test/json_serialization_test.rb @@ -8,9 +8,6 @@ require 'fixtures/comment' class JsonSerializationTest < Test::Unit::TestCase def setup - # Quote all keys (so that we can test against strictly valid JSON). - ActiveSupport::JSON.unquote_hash_key_identifiers = false - @contact = Contact.new( :name => 'Konata Izumi', :age => 16, @@ -70,8 +67,6 @@ class DatabaseConnectedJsonEncodingTest < Test::Unit::TestCase fixtures :authors, :posts, :comments, :tags, :taggings def setup - ActiveSupport::JSON.unquote_hash_key_identifiers = false - @david = authors(:david) end diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 272be35724..b0a3e6aaa6 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *2.0.0 [Preview Release]* (September 29th, 2007) +* Fixed JSON encoding to use quoted keys according to the JSON standard #8762 [choonkat/chuyeow] + * Alias Object#send to send! for Ruby 1.9 forward compatibility. [Jeremy Kemper] * Backport Object#instance_variable_defined? for Ruby < 1.8.6. [Jeremy Kemper] diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index 3654e10b2e..9a9f074847 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -2,8 +2,6 @@ class Hash def to_json #:nodoc: returning result = '{' do result << map do |key, value| - key = ActiveSupport::JSON::Variable.new(key.to_s) if - ActiveSupport::JSON.can_unquote_identifier?(key) "#{ActiveSupport::JSON.encode(key)}: #{ActiveSupport::JSON.encode(value)}" end * ', ' result << '}' diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 64e5779b71..67656109c0 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -10,13 +10,6 @@ end module ActiveSupport module JSON - # When +true+, Hash#to_json will omit quoting string or symbol keys - # if the keys are valid JavaScript identifiers. Note that this is - # technically improper JSON (all object keys must be quoted), so if - # you need strict JSON compliance, set this option to +false+. - mattr_accessor :unquote_hash_key_identifiers - @@unquote_hash_key_identifiers = true - class CircularReferenceError < StandardError end @@ -30,11 +23,6 @@ module ActiveSupport end end - def can_unquote_identifier?(key) #:nodoc: - unquote_hash_key_identifiers && - ActiveSupport::JSON.valid_identifier?(key) - end - protected def raise_on_circular_reference(value) #:nodoc: stack = Thread.current[REFERENCE_STACK_VARIABLE] ||= [] diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb index 325ac9b7a6..0af98f0968 100644 --- a/activesupport/lib/active_support/json/variable.rb +++ b/activesupport/lib/active_support/json/variable.rb @@ -1,6 +1,6 @@ module ActiveSupport module JSON - # A string that returns itself as as its JSON-encoded form. + # A string that returns itself as its JSON-encoded form. class Variable < String def to_json self diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 9ed7683b86..ba468141b4 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -41,21 +41,12 @@ class TestJSONEncoding < Test::Unit::TestCase end end - def setup - unquote(false) - end - - def teardown - unquote(true) - end - def test_hash_encoding assert_equal %({\"a\": \"b\"}), { :a => :b }.to_json assert_equal %({\"a\": 1}), { 'a' => 1 }.to_json assert_equal %({\"a\": [1, 2]}), { 'a' => [1,2] }.to_json - - sorted_json = - '{' + {:a => :b, :c => :d}.to_json[1..-2].split(', ').sort.join(', ') + '}' + + sorted_json = '{' + {:a => :b, :c => :d}.to_json[1..-2].split(', ').sort.join(', ') + '}' assert_equal %({\"a\": \"b\", \"c\": \"d\"}), sorted_json end @@ -72,29 +63,14 @@ class TestJSONEncoding < Test::Unit::TestCase a << a assert_raises(ActiveSupport::JSON::CircularReferenceError) { a.to_json } end - - def test_unquote_hash_key_identifiers + + def test_hash_key_identifiers_are_always_quoted values = {0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B"} assert_equal %w( "$" "A" "A0" "A0B" "_" "a" 0 1 ), object_keys(values.to_json) - unquote(true) { assert_equal %w( $ 0 1 A A0 A0B _ a ), object_keys(values.to_json) } end - - def test_unquote_hash_key_identifiers_ignores_javascript_reserved_words - values = {"hello" => "world", "this" => "that", "with" => "foo"} - unquote(true) { assert_equal %w( "this" "with" hello ), object_keys(values.to_json) } - end - + protected - def unquote(value) - previous_value = ActiveSupport::JSON.unquote_hash_key_identifiers - ActiveSupport::JSON.unquote_hash_key_identifiers = value - yield if block_given? - ensure - ActiveSupport::JSON.unquote_hash_key_identifiers = previous_value if block_given? - end - def object_keys(json_object) json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort end - end -- cgit v1.2.3