Permalink
Browse files

JSON: split encoding and coercion

  • Loading branch information...
1 parent 5e1b46d commit 00ee990443189649e481b2c30945e7a1029d8280 @jeremy jeremy committed Jun 6, 2009
@@ -873,7 +873,7 @@ def to_xml(options={})
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 @@ def to_xml(options={})
#
# 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 @@ def split_options(options = {})
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
@@ -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]
@@ -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'
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,6 +0,0 @@
-class FalseClass
- private
- def rails_to_json(*)
- 'false'
- end
-end
@@ -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
@@ -1,6 +0,0 @@
-class NilClass
- private
- def rails_to_json(*)
- 'null'
- end
-end
@@ -1,6 +0,0 @@
-class Numeric
- private
- def rails_to_json(*)
- to_s
- end
-end
@@ -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
@@ -1,6 +0,0 @@
-class Regexp
- private
- def rails_to_json(*)
- inspect
- end
-end
@@ -1,6 +0,0 @@
-class String
- private
- def rails_to_json(*)
- ActiveSupport::JSON::Encoding.escape(self)
- end
-end
@@ -1,6 +0,0 @@
-class Symbol
- private
- def rails_to_json(*args)
- ActiveSupport::JSON.encode(to_s, *args)
- end
-end
@@ -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
@@ -1,6 +0,0 @@
-class TrueClass
- private
- def rails_to_json(*)
- 'true'
- end
-end
Oops, something went wrong.

0 comments on commit 00ee990

Please sign in to comment.