Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Hash#to_json takes :only or :except options to specific or omit certa…

…in 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
  • Loading branch information...
commit b1968708e12972515fdc8eefdcaff95edbebc76b 1 parent a30a1a9
@jeremy jeremy authored
View
2  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
View
36 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 @@ def @david.favorite_quote; "Constraints are liberating"; end
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
View
4 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)
View
2  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
View
2  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
View
4 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
View
2  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
View
14 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
View
2  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
View
2  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
View
8 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
View
2  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
View
2  activesupport/lib/active_support/json/encoders/string.rb
@@ -17,7 +17,7 @@ module Encoding
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]|
View
4 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
View
2  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
View
2  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
View
4 activesupport/lib/active_support/json/encoding.rb
@@ -17,9 +17,9 @@ class << self
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
View
21 activesupport/test/json/encoding_test.rb
@@ -69,8 +69,29 @@ def test_hash_key_identifiers_are_always_quoted
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
Please sign in to comment.
Something went wrong with that request. Please try again.