aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activeresource/lib/active_resource/base.rb11
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/json.rb87
-rw-r--r--activesupport/lib/active_support/json/decoding.rb35
-rw-r--r--activesupport/lib/active_support/json/encoders/date.rb22
-rw-r--r--activesupport/lib/active_support/json/encoders/date_time.rb22
-rw-r--r--activesupport/lib/active_support/json/encoders/enumerable.rb13
-rw-r--r--activesupport/lib/active_support/json/encoders/false_class.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/hash.rb51
-rw-r--r--activesupport/lib/active_support/json/encoders/nil_class.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/numeric.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/object.rb13
-rw-r--r--activesupport/lib/active_support/json/encoders/regexp.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/string.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/symbol.rb6
-rw-r--r--activesupport/lib/active_support/json/encoders/time.rb24
-rw-r--r--activesupport/lib/active_support/json/encoders/true_class.rb6
-rw-r--r--activesupport/lib/active_support/json/encoding.rb229
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb41
-rw-r--r--activesupport/test/json/encoding_test.rb19
20 files changed, 279 insertions, 332 deletions
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 11a7bbba3e..dbc418bef3 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -873,7 +873,7 @@ module ActiveResource
attributes.to_xml({:root => self.class.element_name}.merge(options))
end
- # Converts the resource to a JSON string representation.
+ # Coerces to a hash for JSON encoding.
#
# ==== Options
# The +options+ are passed to the +to_json+ method on each
@@ -897,8 +897,8 @@ module ActiveResource
#
# person.to_json(:except => ["first_name"])
# # => {"last_name": "Smith"}
- def to_json(options={})
- ActiveSupport::JSON.encode(attributes, options)
+ def as_json(options = nil)
+ attributes.as_json(options)
end
# Returns the serialized string representation of the resource in the configured
@@ -1072,11 +1072,6 @@ module ActiveResource
self.class.__send__(:split_options, options)
end
- # For compatibility with ActiveSupport::JSON.encode
- def rails_to_json(options, *args)
- to_json(options)
- end
-
def method_missing(method_symbol, *arguments) #:nodoc:
method_name = method_symbol.to_s
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 93e0f1aa24..9c5803c52a 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* JSON: +Object#to_json+ calls +as_json+ to coerce itself into something natively encodable like +Hash+, +Integer+, or +String+. Override +as_json+ instead of +to_json+ so you're JSON library agnostic. [Jeremy Kemper]
+
* String #to_time and #to_datetime: handle fractional seconds #864 [Jason Frey]
* Update bundled TZInfo to v0.3.13 [Geoff Buesing]
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index 6d845182fb..3e1d9b1d33 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -1,87 +1,2 @@
-require 'active_support/core_ext/module/delegation'
-require 'active_support/core_ext/module/attribute_accessors'
-
-module ActiveSupport
- # If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format.
- mattr_accessor :use_standard_json_time_format
- # Look for and parse json strings that look like ISO 8601 times.
- mattr_accessor :parse_json_times
-
- module JSON
- # matches YAML-formatted dates
- DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
-
- module Encoding #:nodoc:
- mattr_accessor :escape_regex
-
- ESCAPED_CHARS = {
- "\010" => '\b',
- "\f" => '\f',
- "\n" => '\n',
- "\r" => '\r',
- "\t" => '\t',
- '"' => '\"',
- '\\' => '\\\\',
- '>' => '\u003E',
- '<' => '\u003C',
- '&' => '\u0026'
- }
-
- def self.escape(string)
- string = string.dup.force_encoding(::Encoding::BINARY) if string.respond_to?(:force_encoding)
- json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }.
- gsub(/([\xC0-\xDF][\x80-\xBF]|
- [\xE0-\xEF][\x80-\xBF]{2}|
- [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
- s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&')
- }
- %("#{json}")
- end
- end
-
- class << self
- delegate :decode, :to => :backend
-
- def backend
- unless defined? @backend
- self.backend = defined?(::JSON) ? "JSONGem" : "Yaml"
- end
- @backend
- end
-
- def backend=(name)
- if name.is_a?(Module)
- @backend = name
- else
- require "active_support/json/backends/#{name.to_s.downcase}.rb"
- @backend = ActiveSupport::JSON::Backends::const_get(name)
- end
- end
-
- def with_backend(name)
- old_backend, self.backend = backend, name
- yield
- ensure
- self.backend = old_backend
- end
- end
- end
-
- class << self
- attr_reader :escape_html_entities_in_json
-
- def escape_html_entities_in_json=(value)
- ActiveSupport::JSON::Encoding.escape_regex = \
- if value
- /[\010\f\n\r\t"\\><&]/
- else
- /[\010\f\n\r\t"\\]/
- end
- @escape_html_entities_in_json = value
- end
- end
-end
-
-ActiveSupport.escape_html_entities_in_json = true
-
+require 'active_support/json/decoding'
require 'active_support/json/encoding'
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
new file mode 100644
index 0000000000..5d4caa362f
--- /dev/null
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -0,0 +1,35 @@
+require 'active_support/core_ext/module/attribute_accessors'
+
+module ActiveSupport
+ # Look for and parse json strings that look like ISO 8601 times.
+ mattr_accessor :parse_json_times
+
+ module JSON
+ class << self
+ delegate :decode, :to => :backend
+
+ def backend
+ @backend || begin
+ self.backend = "Yaml"
+ @backend
+ end
+ end
+
+ def backend=(name)
+ if name.is_a?(Module)
+ @backend = name
+ else
+ require "active_support/json/backends/#{name.to_s.downcase}.rb"
+ @backend = ActiveSupport::JSON::Backends::const_get(name)
+ end
+ end
+
+ def with_backend(name)
+ old_backend, self.backend = backend, name
+ yield
+ ensure
+ self.backend = old_backend
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb
deleted file mode 100644
index 9adb3c20e2..0000000000
--- a/activesupport/lib/active_support/json/encoders/date.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class Date
- private
- # Returns a JSON string representing the date. If ActiveSupport.use_standard_json_time_format is set to true, the
- # ISO 8601 format is used.
- #
- # ==== Examples
- #
- # # With ActiveSupport.use_standard_json_time_format = true
- # Date.new(2005,2,1).to_json
- # # => "2005-02-01"
- #
- # # With ActiveSupport.use_standard_json_time_format = false
- # Date.new(2005,2,1).to_json
- # # => "2005/02/01"
- def rails_to_json(*)
- if ActiveSupport.use_standard_json_time_format
- %("#{strftime("%Y-%m-%d")}")
- else
- %("#{strftime("%Y/%m/%d")}")
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb
deleted file mode 100644
index 3a29292b24..0000000000
--- a/activesupport/lib/active_support/json/encoders/date_time.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-class DateTime
- private
- # Returns a JSON string representing the datetime. If ActiveSupport.use_standard_json_time_format is set to true, the
- # ISO 8601 format is used.
- #
- # ==== Examples
- #
- # # With ActiveSupport.use_standard_json_time_format = true
- # DateTime.civil(2005,2,1,15,15,10).to_json
- # # => "2005-02-01T15:15:10+00:00"
- #
- # # With ActiveSupport.use_standard_json_time_format = false
- # DateTime.civil(2005,2,1,15,15,10).to_json
- # # => "2005/02/01 15:15:10 +0000"
- def rails_to_json(*)
- if ActiveSupport.use_standard_json_time_format
- xmlschema.inspect
- else
- strftime('"%Y/%m/%d %H:%M:%S %z"')
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/enumerable.rb b/activesupport/lib/active_support/json/encoders/enumerable.rb
deleted file mode 100644
index 898990a59c..0000000000
--- a/activesupport/lib/active_support/json/encoders/enumerable.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module Enumerable
- private
- # Returns a JSON string representing the enumerable. Any +options+
- # given will be passed on to its elements. For example:
- #
- # users = User.find(:all)
- # # => users.to_json(:only => :name)
- #
- # will pass the <tt>:only => :name</tt> option to each user.
- def rails_to_json(options = nil, *args) #:nodoc:
- "[#{map { |value| ActiveSupport::JSON.encode(value, options, *args) } * ','}]"
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/false_class.rb b/activesupport/lib/active_support/json/encoders/false_class.rb
deleted file mode 100644
index eb975fe542..0000000000
--- a/activesupport/lib/active_support/json/encoders/false_class.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class FalseClass
- private
- def rails_to_json(*)
- 'false'
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb
deleted file mode 100644
index 4771484843..0000000000
--- a/activesupport/lib/active_support/json/encoders/hash.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'active_support/core_ext/array/wrap'
-
-class Hash
- private
- # Returns a JSON string representing the hash.
- #
- # Without any +options+, the returned JSON string will include all
- # the hash keys. For example:
- #
- # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json
- # # => {"name": "Konata Izumi", "1": 2, "age": 16}
- #
- # The keys in the JSON string are unordered due to the nature of hashes.
- #
- # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the
- # attributes included, and will accept 1 or more hash keys to include/exclude.
- #
- # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:only => [:name, 'age'])
- # # => {"name": "Konata Izumi", "age": 16}
- #
- # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:except => 1)
- # # => {"name": "Konata Izumi", "age": 16}
- #
- # The +options+ also filter down to any hash values. This is particularly
- # useful for converting hashes containing ActiveRecord objects or any object
- # that responds to options in their <tt>to_json</tt> method. For example:
- #
- # users = User.find(:all)
- # { :users => users, :count => users.size }.to_json(:include => :posts)
- #
- # would pass the <tt>:include => :posts</tt> option to <tt>users</tt>,
- # allowing the posts association in the User model to be converted to JSON
- # as well.
- def rails_to_json(options = nil, *args) #:nodoc:
- hash_keys = self.keys
-
- if options
- if except = options[:except]
- hash_keys = hash_keys - Array.wrap(except)
- elsif only = options[:only]
- hash_keys = hash_keys & Array.wrap(only)
- end
- end
-
- result = '{'
- result << hash_keys.map do |key|
- "#{ActiveSupport::JSON.encode(key.to_s)}:#{ActiveSupport::JSON.encode(self[key], options, *args)}"
- end * ','
- result << '}'
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/nil_class.rb b/activesupport/lib/active_support/json/encoders/nil_class.rb
deleted file mode 100644
index 8c51dba384..0000000000
--- a/activesupport/lib/active_support/json/encoders/nil_class.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class NilClass
- private
- def rails_to_json(*)
- 'null'
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/numeric.rb b/activesupport/lib/active_support/json/encoders/numeric.rb
deleted file mode 100644
index c7cd0df1d7..0000000000
--- a/activesupport/lib/active_support/json/encoders/numeric.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Numeric
- private
- def rails_to_json(*)
- to_s
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/object.rb b/activesupport/lib/active_support/json/encoders/object.rb
deleted file mode 100644
index 9cc12d91ac..0000000000
--- a/activesupport/lib/active_support/json/encoders/object.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'active_support/core_ext/object/instance_variables'
-
-class Object
- # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
- def to_json(options = nil)
- ActiveSupport::JSON.encode(self, options)
- end
-
- private
- def rails_to_json(*args)
- ActiveSupport::JSON.encode(instance_values, *args)
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/regexp.rb b/activesupport/lib/active_support/json/encoders/regexp.rb
deleted file mode 100644
index ee42db4d02..0000000000
--- a/activesupport/lib/active_support/json/encoders/regexp.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Regexp
- private
- def rails_to_json(*)
- inspect
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/string.rb b/activesupport/lib/active_support/json/encoders/string.rb
deleted file mode 100644
index 4a6b21c1c0..0000000000
--- a/activesupport/lib/active_support/json/encoders/string.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class String
- private
- def rails_to_json(*)
- ActiveSupport::JSON::Encoding.escape(self)
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/symbol.rb b/activesupport/lib/active_support/json/encoders/symbol.rb
deleted file mode 100644
index d575350a4e..0000000000
--- a/activesupport/lib/active_support/json/encoders/symbol.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Symbol
- private
- def rails_to_json(*args)
- ActiveSupport::JSON.encode(to_s, *args)
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb
deleted file mode 100644
index d434b9aace..0000000000
--- a/activesupport/lib/active_support/json/encoders/time.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'active_support/core_ext/time/conversions'
-
-class Time
- private
- # Returns a JSON string representing the time. If ActiveSupport.use_standard_json_time_format is set to true, the
- # ISO 8601 format is used.
- #
- # ==== Examples
- #
- # # With ActiveSupport.use_standard_json_time_format = true
- # Time.utc(2005,2,1,15,15,10).to_json
- # # => "2005-02-01T15:15:10Z"
- #
- # # With ActiveSupport.use_standard_json_time_format = false
- # Time.utc(2005,2,1,15,15,10).to_json
- # # => "2005/02/01 15:15:10 +0000"
- def rails_to_json(*)
- if ActiveSupport.use_standard_json_time_format
- xmlschema.inspect
- else
- %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}")
- end
- end
-end
diff --git a/activesupport/lib/active_support/json/encoders/true_class.rb b/activesupport/lib/active_support/json/encoders/true_class.rb
deleted file mode 100644
index bc25a6db78..0000000000
--- a/activesupport/lib/active_support/json/encoders/true_class.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class TrueClass
- private
- def rails_to_json(*)
- 'true'
- end
-end
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 5fefe5b88b..97e573f7a6 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -1,33 +1,214 @@
+require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/object/instance_variables'
+require 'active_support/deprecation'
+
+# Hack to load json gem first so we can overwrite its to_json.
+begin
+ require 'json'
+rescue LoadError
+end
+
module ActiveSupport
+ class << self
+ delegate :use_standard_json_time_format, :use_standard_json_time_format=,
+ :escape_html_entities_in_json, :escape_html_entities_in_json=,
+ :to => :'ActiveSupport::JSON::Encoding'
+ end
+
module JSON
- class CircularReferenceError < StandardError
+ # matches YAML-formatted dates
+ DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
+
+ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
+ def self.encode(value, options = nil)
+ Encoding::Encoder.new(options).encode(value)
end
- # Converts a Ruby object into a JSON string.
- def self.encode(value, options = nil, seen = nil)
- seen ||= []
- if seen.any? { |object| object.equal?(value) }
- raise CircularReferenceError, 'object references itself'
+ module Encoding #:nodoc:
+ class CircularReferenceError < StandardError; end
+
+ class Encoder
+ attr_reader :options
+
+ def initialize(options = nil)
+ @options = options
+ @seen = []
+ end
+
+ def encode(value)
+ check_for_circular_references(value) do
+ value.as_json(options).encode_json(self)
+ end
+ end
+
+ def escape(string)
+ Encoding.escape(string)
+ end
+
+ private
+ def check_for_circular_references(value)
+ if @seen.any? { |object| object.equal?(value) }
+ raise CircularReferenceError, 'object references itself'
+ end
+ @seen.unshift value
+ yield
+ ensure
+ @seen.shift
+ end
+ end
+
+
+ ESCAPED_CHARS = {
+ "\010" => '\b',
+ "\f" => '\f',
+ "\n" => '\n',
+ "\r" => '\r',
+ "\t" => '\t',
+ '"' => '\"',
+ '\\' => '\\\\',
+ '>' => '\u003E',
+ '<' => '\u003C',
+ '&' => '\u0026' }
+
+ class << self
+ # If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format.
+ attr_accessor :use_standard_json_time_format
+
+ attr_accessor :escape_regex
+ attr_reader :escape_html_entities_in_json
+
+ def escape_html_entities_in_json=(value)
+ self.escape_regex = \
+ if @escape_html_entities_in_json = value
+ /[\010\f\n\r\t"\\><&]/
+ else
+ /[\010\f\n\r\t"\\]/
+ end
+ end
+
+ def escape(string)
+ json = '"' + string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
+ json.force_encoding('ascii-8bit') if respond_to?(:force_encoding)
+ json.gsub(/([\xC0-\xDF][\x80-\xBF]|
+ [\xE0-\xEF][\x80-\xBF]{2}|
+ [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
+ s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&')
+ } + '"'
+ end
+ end
+
+ self.escape_html_entities_in_json = true
+ end
+
+ CircularReferenceError = Deprecation::DeprecatedConstantProxy.new('ActiveSupport::JSON::CircularReferenceError', Encoding::CircularReferenceError)
+ end
+end
+
+class Object
+ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
+ def to_json(options = nil)
+ ActiveSupport::JSON.encode(self, options)
+ end
+
+ def as_json(options = nil) instance_values end #:nodoc:
+end
+
+# A string that returns itself as its JSON-encoded form.
+class ActiveSupport::JSON::Variable < String
+ def as_json(options = nil) self end #:nodoc:
+ def encode_json(encoder) self end #:nodoc:
+end
+
+class TrueClass
+ AS_JSON = ActiveSupport::JSON::Variable.new('true').freeze
+ def as_json(options = nil) AS_JSON end #:nodoc:
+end
+
+class FalseClass
+ AS_JSON = ActiveSupport::JSON::Variable.new('false').freeze
+ def as_json(options = nil) AS_JSON end #:nodoc:
+end
+
+class NilClass
+ AS_JSON = ActiveSupport::JSON::Variable.new('null').freeze
+ def as_json(options = nil) AS_JSON end #:nodoc:
+end
+
+class String
+ def as_json(options = nil) self end #:nodoc:
+ def encode_json(encoder) encoder.escape(self) end #:nodoc:
+end
+
+class Symbol
+ def as_json(options = nil) to_s end #:nodoc:
+end
+
+class Numeric
+ def as_json(options = nil) self end #:nodoc:
+ def encode_json(encoder) to_s end #:nodoc:
+end
+
+class Regexp
+ def as_json(options = nil) self end #:nodoc:
+ def encode_json(encoder) inspect end #:nodoc:
+end
+
+module Enumerable
+ def as_json(options = nil) to_a end #:nodoc:
+end
+
+class Array
+ def as_json(options = nil) self end #:nodoc:
+ def encode_json(encoder) "[#{map { |v| encoder.encode(v) } * ','}]" end #:nodoc:
+end
+
+class Hash
+ def as_json(options = nil) #:nodoc:
+ if options
+ if attrs = options[:only]
+ slice(*Array.wrap(attrs))
+ elsif attrs = options[:except]
+ except(*Array.wrap(attrs))
+ else
+ self
end
- seen << value
- value.__send__(:rails_to_json, options, seen)
- ensure
- seen.pop
+ else
+ self
+ end
+ end
+
+ def encode_json(encoder)
+ "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v)}" } * ','}}"
+ end
+end
+
+class Time
+ def as_json(options = nil) #:nodoc:
+ if ActiveSupport.use_standard_json_time_format
+ xmlschema
+ else
+ %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
end
end
end
-require 'active_support/json/variable'
-require 'active_support/json/encoders/date'
-require 'active_support/json/encoders/date_time'
-require 'active_support/json/encoders/enumerable'
-require 'active_support/json/encoders/false_class'
-require 'active_support/json/encoders/hash'
-require 'active_support/json/encoders/nil_class'
-require 'active_support/json/encoders/numeric'
-require 'active_support/json/encoders/object'
-require 'active_support/json/encoders/regexp'
-require 'active_support/json/encoders/string'
-require 'active_support/json/encoders/symbol'
-require 'active_support/json/encoders/time'
-require 'active_support/json/encoders/true_class'
+class Date
+ def as_json(options = nil) #:nodoc:
+ if ActiveSupport.use_standard_json_time_format
+ strftime("%Y-%m-%d")
+ else
+ strftime("%Y/%m/%d")
+ end
+ end
+end
+
+class DateTime
+ def as_json(options = nil) #:nodoc:
+ if ActiveSupport.use_standard_json_time_format
+ xmlschema
+ else
+ strftime('%Y/%m/%d %H:%M:%S %z')
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 069842c6c3..4907fae9d6 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -118,6 +118,27 @@ module ActiveSupport
end
alias_method :iso8601, :xmlschema
+ # Coerces the date to a string for JSON encoding.
+ #
+ # ISO 8601 format is used if ActiveSupport::JSON::Encoding.use_standard_json_time_format is set.
+ #
+ # ==== Examples
+ #
+ # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
+ # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
+ # # => "2005-02-01T15:15:10Z"
+ #
+ # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
+ # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
+ # # => "2005/02/01 15:15:10 +0000"
+ def as_json(options = nil)
+ if ActiveSupport::JSON::Encoding.use_standard_json_time_format
+ xmlschema
+ else
+ %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
+ end
+ end
+
def to_yaml(options = {})
if options.kind_of?(YAML::Emitter)
utc.to_yaml(options)
@@ -301,26 +322,6 @@ module ActiveSupport
end
private
- # Returns a JSON string representing the TimeWithZone. If ActiveSupport.use_standard_json_time_format is set to
- # true, the ISO 8601 format is used.
- #
- # ==== Examples
- #
- # # With ActiveSupport.use_standard_json_time_format = true
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
- # # => "2005-02-01T15:15:10Z"
- #
- # # With ActiveSupport.use_standard_json_time_format = false
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
- # # => "2005/02/01 15:15:10 +0000"
- def rails_to_json(*)
- if !ActiveSupport.respond_to?(:use_standard_json_time_format) || ActiveSupport.use_standard_json_time_format
- xmlschema.inspect
- else
- %("#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}")
- end
- end
-
def get_period_and_ensure_valid_local_time
# we don't want a Time.local instance enforcing its own DST rules as well,
# so transfer time values to a utc constructor if necessary
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 1a0e6d543c..983235d06c 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -9,6 +9,12 @@ class TestJSONEncoding < Test::Unit::TestCase
end
end
+ class Custom
+ def as_json(options)
+ 'custom'
+ end
+ end
+
TrueTests = [[ true, %(true) ]]
FalseTests = [[ false, %(false) ]]
NilTests = [[ nil, %(null) ]]
@@ -27,6 +33,7 @@ class TestJSONEncoding < Test::Unit::TestCase
[ :"a b", %("a b") ]]
ObjectTests = [[ Foo.new(1, 2), %({\"a\":1,\"b\":2}) ]]
+ CustomTests = [[ Custom.new, '"custom"' ]]
VariableTests = [[ ActiveSupport::JSON::Variable.new('foo'), 'foo'],
[ ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")']]
@@ -76,7 +83,7 @@ class TestJSONEncoding < Test::Unit::TestCase
def test_exception_raised_when_encoding_circular_reference
a = [1]
a << a
- assert_raise(ActiveSupport::JSON::CircularReferenceError) { ActiveSupport::JSON.encode(a) }
+ assert_raise(ActiveSupport::JSON::Encoding::CircularReferenceError) { ActiveSupport::JSON.encode(a) }
end
def test_hash_key_identifiers_are_always_quoted
@@ -129,11 +136,9 @@ end
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'].send(:rails_to_json, json_options)
+ value, options = Object.new, Object.new
+ def value.as_json(options) options end
+ def options.encode_json(encoder) self end
+ assert_equal options, ActiveSupport::JSON.encode(value, options)
end
end