diff options
author | Jeremy Kemper <jeremy@bitsweat.net> | 2007-10-04 03:28:42 +0000 |
---|---|---|
committer | Jeremy Kemper <jeremy@bitsweat.net> | 2007-10-04 03:28:42 +0000 |
commit | b1968708e12972515fdc8eefdcaff95edbebc76b (patch) | |
tree | 93c179fda5d5428bb12bbdb4332f4450d523f77c | |
parent | a30a1a9d5f06f404421d65393bcf9d73885789cb (diff) | |
download | rails-b1968708e12972515fdc8eefdcaff95edbebc76b.tar.gz rails-b1968708e12972515fdc8eefdcaff95edbebc76b.tar.bz2 rails-b1968708e12972515fdc8eefdcaff95edbebc76b.zip |
Hash#to_json takes :only or :except options to specific or omit certain hash keys. Enumerable#to_json passes through its options to each element. Closes #9751.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7736 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
18 files changed, 88 insertions, 27 deletions
diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb index 97025ae4d3..8b1b8299f8 100644 --- a/activerecord/lib/active_record/serializers/json_serializer.rb +++ b/activerecord/lib/active_record/serializers/json_serializer.rb @@ -1,6 +1,6 @@ module ActiveRecord #:nodoc: module Serialization - def to_json(options = {}, &block) + def to_json(options = {}) JsonSerializer.new(self, options).to_s end diff --git a/activerecord/test/json_serialization_test.rb b/activerecord/test/json_serialization_test.rb index d12e7c42c6..eb4f90cf0f 100644 --- a/activerecord/test/json_serialization_test.rb +++ b/activerecord/test/json_serialization_test.rb @@ -68,11 +68,12 @@ class DatabaseConnectedJsonEncodingTest < Test::Unit::TestCase def setup @david = authors(:david) + @mary = authors(:mary) end def test_includes_uses_association_name json = @david.to_json(:include => :posts) - + assert_match %r{"posts": \[}, json assert_match %r{"id": 1}, json @@ -140,4 +141,37 @@ class DatabaseConnectedJsonEncodingTest < Test::Unit::TestCase assert_match %r{"favorite_quote": "Constraints are liberating"}, json assert_equal %r{"favorite_quote": }.match(json).size, 1 end + + def test_should_allow_only_option_for_list_of_authors + authors = [@david, @mary] + + assert_equal %([{"name": "David"}, {"name": "Mary"}]), authors.to_json(:only => :name) + end + + def test_should_allow_except_option_for_list_of_authors + authors = [@david, @mary] + + assert_equal %([{"id": 1}, {"id": 2}]), authors.to_json(:except => [:name, :author_address_id]) + end + + def test_should_allow_includes_for_list_of_authors + authors = [@david, @mary] + json = authors.to_json( + :only => :name, + :include => { + :posts => { :only => :id } + } + ) + + assert_equal %([{"name": "David", "posts": [{"id": 1}, {"id": 2}, {"id": 4}, {"id": 5}, {"id": 6}]}, {"name": "Mary", "posts": [{"id": 7}]}]), json + end + + def test_should_allow_options_for_hash_of_authors + authors_hash = { + 1 => @david, + 2 => @mary + } + + assert_equal %({1: {"name": "David"}}), authors_hash.to_json(:only => [1, :name]) + end end
\ No newline at end of file diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 33e96c0e95..089c50d545 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,8 +1,10 @@ *SVN* +* Hash#to_json takes :only or :except options to specific or omit certain hash keys. Enumerable#to_json passes through its options to each element. #9751 [Chu Yeow] + * BufferedLogger#auto_flushing = N flushes the log every N messages. Buffers with an array instead of string. [Jeremy Kemper] -* Fixed Date#xmlschema for dates outside the range of what can be created with Time #9744 [gbuesing] +* Fixed Date#xmlschema for dates outside the range of what can be created with Time #9744 [Geoff Buesing] *2.0.0 [Preview Release]* (September 29th, 2007) diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb index ee1a472f3f..de59e1b338 100644 --- a/activesupport/lib/active_support/json/encoders/date.rb +++ b/activesupport/lib/active_support/json/encoders/date.rb @@ -1,5 +1,5 @@ class Date - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: %("#{strftime("%m/%d/%Y")}") end end diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb index 28cb18977d..229cefc007 100644 --- a/activesupport/lib/active_support/json/encoders/date_time.rb +++ b/activesupport/lib/active_support/json/encoders/date_time.rb @@ -1,5 +1,5 @@ class DateTime - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: %("#{strftime("%m/%d/%Y %H:%M:%S %Z")}") end end diff --git a/activesupport/lib/active_support/json/encoders/enumerable.rb b/activesupport/lib/active_support/json/encoders/enumerable.rb index 150d233939..d180049663 100644 --- a/activesupport/lib/active_support/json/encoders/enumerable.rb +++ b/activesupport/lib/active_support/json/encoders/enumerable.rb @@ -1,5 +1,5 @@ module Enumerable - def to_json #:nodoc: - "[#{map { |value| ActiveSupport::JSON.encode(value) } * ', '}]" + def to_json(options = {}) #:nodoc: + "[#{map { |value| ActiveSupport::JSON.encode(value, options) } * ', '}]" end end diff --git a/activesupport/lib/active_support/json/encoders/false_class.rb b/activesupport/lib/active_support/json/encoders/false_class.rb index 78524e2a03..bf0844334b 100644 --- a/activesupport/lib/active_support/json/encoders/false_class.rb +++ b/activesupport/lib/active_support/json/encoders/false_class.rb @@ -1,5 +1,5 @@ class FalseClass - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: 'false' end end diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index 9a9f074847..14b91a76a1 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -1,8 +1,16 @@ class Hash - def to_json #:nodoc: + def to_json(options = {}) #:nodoc: + hash_keys = self.keys + + if options[:except] + hash_keys = hash_keys - Array(options[:except]) + elsif options[:only] + hash_keys = hash_keys & Array(options[:only]) + end + returning result = '{' do - result << map do |key, value| - "#{ActiveSupport::JSON.encode(key)}: #{ActiveSupport::JSON.encode(value)}" + result << hash_keys.map do |key| + "#{ActiveSupport::JSON.encode(key)}: #{ActiveSupport::JSON.encode(self[key], options)}" end * ', ' result << '}' end diff --git a/activesupport/lib/active_support/json/encoders/nil_class.rb b/activesupport/lib/active_support/json/encoders/nil_class.rb index 98bb6fb677..4763471ac4 100644 --- a/activesupport/lib/active_support/json/encoders/nil_class.rb +++ b/activesupport/lib/active_support/json/encoders/nil_class.rb @@ -1,5 +1,5 @@ class NilClass - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: 'null' end end diff --git a/activesupport/lib/active_support/json/encoders/numeric.rb b/activesupport/lib/active_support/json/encoders/numeric.rb index 5d9b2eea9e..38713fb369 100644 --- a/activesupport/lib/active_support/json/encoders/numeric.rb +++ b/activesupport/lib/active_support/json/encoders/numeric.rb @@ -1,5 +1,5 @@ class Numeric - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: to_s end end diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb index 51852e17cb..6da0d1d1c1 100644 --- a/activesupport/lib/active_support/json/encoders/object.rb +++ b/activesupport/lib/active_support/json/encoders/object.rb @@ -1,10 +1,6 @@ class Object # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - # - # Account.find(1).to_json - # => "{attributes: {username: \"foo\", id: \"1\", password: \"bar\"}}" - # - def to_json - ActiveSupport::JSON.encode(instance_values) + def to_json(options = {}) + ActiveSupport::JSON.encode(instance_values, options) end end diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb index a3f32eafa2..b6116b70b5 100644 --- a/activesupport/lib/active_support/json/encoders/regexp.rb +++ b/activesupport/lib/active_support/json/encoders/regexp.rb @@ -1,5 +1,5 @@ class Regexp - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: inspect end end diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb index f357262fc6..963cd10969 100644 --- a/activesupport/lib/active_support/json/encoders/string.rb +++ b/activesupport/lib/active_support/json/encoders/string.rb @@ -17,7 +17,7 @@ module ActiveSupport end class String - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: '"' + gsub(/[\010\f\n\r\t"\\><]/) { |s| ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s] }.gsub(/([\xC0-\xDF][\x80-\xBF]| diff --git a/activesupport/lib/active_support/json/encoders/symbol.rb b/activesupport/lib/active_support/json/encoders/symbol.rb index 57291e5448..485112f97c 100644 --- a/activesupport/lib/active_support/json/encoders/symbol.rb +++ b/activesupport/lib/active_support/json/encoders/symbol.rb @@ -1,5 +1,5 @@ class Symbol - def to_json #:nodoc: - ActiveSupport::JSON.encode(to_s) + def to_json(options = {}) #:nodoc: + ActiveSupport::JSON.encode(to_s, options) end end diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb index 080e9392f1..b9b52be9ed 100644 --- a/activesupport/lib/active_support/json/encoders/time.rb +++ b/activesupport/lib/active_support/json/encoders/time.rb @@ -1,5 +1,5 @@ class Time - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: %("#{strftime("%m/%d/%Y %H:%M:%S %Z")}") end end diff --git a/activesupport/lib/active_support/json/encoders/true_class.rb b/activesupport/lib/active_support/json/encoders/true_class.rb index f652f8bb54..037d812b3f 100644 --- a/activesupport/lib/active_support/json/encoders/true_class.rb +++ b/activesupport/lib/active_support/json/encoders/true_class.rb @@ -1,5 +1,5 @@ class TrueClass - def to_json #:nodoc: + def to_json(options = nil) #:nodoc: 'true' end end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 67656109c0..adfbfd5f72 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -17,9 +17,9 @@ module ActiveSupport REFERENCE_STACK_VARIABLE = :json_reference_stack #:nodoc: # Converts a Ruby object into a JSON string. - def encode(value) + def encode(value, options = {}) raise_on_circular_reference(value) do - value.send(:to_json) + value.send(:to_json, options) end end diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index ba468141b4..dee5b928d3 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -69,8 +69,29 @@ class TestJSONEncoding < Test::Unit::TestCase assert_equal %w( "$" "A" "A0" "A0B" "_" "a" 0 1 ), object_keys(values.to_json) end + def test_hash_should_allow_key_filtering_with_only + assert_equal %({"a": 1}), { 'a' => 1, :b => 2, :c => 3 }.to_json(:only => 'a') + end + + def test_hash_should_allow_key_filtering_with_except + assert_equal %({"b": 2}), { 'foo' => 'bar', :b => 2, :c => 3 }.to_json(:except => ['foo', :c]) + end + protected def object_keys(json_object) json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort end end + +uses_mocha 'JsonOptionsTests' do + class JsonOptionsTests < Test::Unit::TestCase + def test_enumerable_should_passthrough_options_to_elements + json_options = { :include => :posts } + ActiveSupport::JSON.expects(:encode).with(1, json_options) + ActiveSupport::JSON.expects(:encode).with(2, json_options) + ActiveSupport::JSON.expects(:encode).with('foo', json_options) + + [1, 2, 'foo'].to_json(json_options) + end + end +end |