aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
authorSam Stephenson <sam@37signals.com>2005-12-27 03:11:03 +0000
committerSam Stephenson <sam@37signals.com>2005-12-27 03:11:03 +0000
commite567a5eb1afe1ac38f1da37f1c1e3922bbf79d2a (patch)
tree47baca37670f0ad23d803c2f939199147efe4287 /activesupport/lib/active_support
parent0b55ce7191b167d67ec7ccc7eb8db2e5fac4f2e1 (diff)
downloadrails-e567a5eb1afe1ac38f1da37f1c1e3922bbf79d2a.tar.gz
rails-e567a5eb1afe1ac38f1da37f1c1e3922bbf79d2a.tar.bz2
rails-e567a5eb1afe1ac38f1da37f1c1e3922bbf79d2a.zip
Add ActiveSupport::JSON and Object#to_json for converting Ruby objects to JSON strings
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3356 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/core_ext/object_and_class.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/string.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/iterators.rb17
-rw-r--r--activesupport/lib/active_support/json.rb28
-rw-r--r--activesupport/lib/active_support/json/encoders.rb25
-rw-r--r--activesupport/lib/active_support/json/encoders/core.rb61
6 files changed, 144 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/core_ext/object_and_class.rb b/activesupport/lib/active_support/core_ext/object_and_class.rb
index aef1f22c6f..4856a9f5d5 100644
--- a/activesupport/lib/active_support/core_ext/object_and_class.rb
+++ b/activesupport/lib/active_support/core_ext/object_and_class.rb
@@ -54,6 +54,17 @@ class Object #:nodoc:
def with_options(options)
yield ActiveSupport::OptionMerger.new(self, options)
end
+
+ def instance_values
+ instance_variables.inject({}) do |values, name|
+ values[name[1..-1]] = instance_variable_get(name)
+ values
+ end
+ end
+
+ def to_json
+ ActiveSupport::JSON.encode(self)
+ end
end
class Class #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb
index 979f8a0515..240e1ff1da 100644
--- a/activesupport/lib/active_support/core_ext/string.rb
+++ b/activesupport/lib/active_support/core_ext/string.rb
@@ -2,10 +2,12 @@ require File.dirname(__FILE__) + '/string/inflections'
require File.dirname(__FILE__) + '/string/conversions'
require File.dirname(__FILE__) + '/string/access'
require File.dirname(__FILE__) + '/string/starts_ends_with'
+require File.dirname(__FILE__) + '/string/iterators'
class String #:nodoc:
include ActiveSupport::CoreExtensions::String::Access
include ActiveSupport::CoreExtensions::String::Conversions
include ActiveSupport::CoreExtensions::String::Inflections
include ActiveSupport::CoreExtensions::String::StartsEndsWith
+ include ActiveSupport::CoreExtensions::String::Iterators
end
diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb
new file mode 100644
index 0000000000..73114d9d5f
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/string/iterators.rb
@@ -0,0 +1,17 @@
+require 'strscan'
+
+module ActiveSupport #:nodoc:
+ module CoreExtensions #:nodoc:
+ module String #:nodoc:
+ # Custom string iterators
+ module Iterators
+ # Yields a single-character string for each character in the string.
+ # When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.
+ def each_char
+ scanner, char = StringScanner.new(self), /./mu
+ loop { yield(scanner.scan(char) || break) }
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
new file mode 100644
index 0000000000..77c7225c66
--- /dev/null
+++ b/activesupport/lib/active_support/json.rb
@@ -0,0 +1,28 @@
+require 'active_support/json/encoders'
+
+module ActiveSupport
+ module JSON #:nodoc:
+ class CircularReferenceError < StandardError; end
+
+ class << self
+ REFERENCE_STACK_VARIABLE = :json_reference_stack
+
+ def encode(value)
+ raise_on_circular_reference(value) do
+ Encoders[value.class].call(value)
+ end
+ end
+
+ protected
+ def raise_on_circular_reference(value)
+ stack = Thread.current[REFERENCE_STACK_VARIABLE] ||= []
+ raise CircularReferenceError, 'object references itself' if
+ stack.include? value
+ stack << value
+ yield
+ ensure
+ stack.pop
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/json/encoders.rb b/activesupport/lib/active_support/json/encoders.rb
new file mode 100644
index 0000000000..c3e3619f59
--- /dev/null
+++ b/activesupport/lib/active_support/json/encoders.rb
@@ -0,0 +1,25 @@
+module ActiveSupport
+ module JSON #:nodoc:
+ module Encoders
+ mattr_accessor :encoders
+ @@encoders = {}
+
+ class << self
+ def define_encoder(klass, &block)
+ encoders[klass] = block
+ end
+
+ def [](klass)
+ klass.ancestors.each do |k|
+ encoder = encoders[k]
+ return encoder if encoder
+ end
+ end
+ end
+ end
+ end
+end
+
+Dir[File.dirname(__FILE__) + '/encoders/*.rb'].each do |file|
+ require file[0..-4]
+end
diff --git a/activesupport/lib/active_support/json/encoders/core.rb b/activesupport/lib/active_support/json/encoders/core.rb
new file mode 100644
index 0000000000..003c938be4
--- /dev/null
+++ b/activesupport/lib/active_support/json/encoders/core.rb
@@ -0,0 +1,61 @@
+module ActiveSupport
+ module JSON #:nodoc:
+ module Encoders
+ define_encoder Object do |object|
+ object.instance_values.to_json
+ end
+
+ define_encoder TrueClass do
+ 'true'
+ end
+
+ define_encoder FalseClass do
+ 'false'
+ end
+
+ define_encoder NilClass do
+ 'null'
+ end
+
+ define_encoder String do |string|
+ returning value = '"' do
+ string.each_char do |char|
+ value << case
+ when char == "\010": '\b'
+ when char == "\f": '\f'
+ when char == "\n": '\n'
+ when char == "\r": '\r'
+ when char == "\t": '\t'
+ when char == '"': '\"'
+ when char == '\\': '\\\\'
+ when char.length > 1: "\\u#{'%04x' % char.unpack('U').first}"
+ else; char
+ end
+ end
+ value << '"'
+ end
+ end
+
+ define_encoder Numeric do |numeric|
+ numeric.to_s
+ end
+
+ define_encoder Symbol do |symbol|
+ symbol.to_s.to_json
+ end
+
+ define_encoder Enumerable do |enumerable|
+ "[#{enumerable.map { |value| value.to_json } * ', '}]"
+ end
+
+ define_encoder Hash do |hash|
+ returning result = '{' do
+ result << hash.map do |pair|
+ pair.map { |value| value.to_json } * ': '
+ end * ', '
+ result << '}'
+ end
+ end
+ end
+ end
+end