aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-11-30 12:08:46 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-11-30 12:08:46 +0000
commita049c43c65822b8736791d71c3d51dcca0f75cfa (patch)
tree06b51542816c4261d2b45e4f5f7077635c83bbc2 /lib
parente46a61775933d1ce9207fde4422ad536fed4846a (diff)
downloadruby-a049c43c65822b8736791d71c3d51dcca0f75cfa.tar.gz
* lib/json.rb, lib/json/add/{core.rb, rails.rb},
test/json/test_json_rails.rb: additional files of JSON 1.1.2. [ruby-dev:32405] -- M lib/json.rb A lib/json/add A lib/json/add/core.rb A lib/json/add/rails.rb A test/json/test_json_rails.rb git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14051 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/json.rb26
-rw-r--r--lib/json/add/core.rb120
-rw-r--r--lib/json/add/rails.rb58
3 files changed, 192 insertions, 12 deletions
diff --git a/lib/json.rb b/lib/json.rb
index bb711c1724..3b0b711550 100644
--- a/lib/json.rb
+++ b/lib/json.rb
@@ -62,6 +62,13 @@ require 'json/common'
# you
# require 'json/add/core'
#
+# After requiring this you can, e. g., serialise/deserialise Ruby ranges:
+#
+# JSON JSON(1..10) # => 1..10
+#
+# To find out how to add JSON support to other or your own classes, read the
+# Examples section below.
+#
# To get the best compatibility to rails' JSON implementation, you can
# require 'json/add/rails'
#
@@ -125,11 +132,6 @@ require 'json/common'
# json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
#
-# It's also possible to call the #to_json method directly.
-#
-# json = [1, 2, {"a"=>3.141}, false, true, nil, 4..10].to_json
-# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
-#
# To create a valid JSON text you have to make sure, that the output is
# embedded in either a JSON array [] or a JSON object {}. The easiest way to do
# this, is by putting your values in a Ruby Array or Hash instance.
@@ -145,10 +147,10 @@ require 'json/common'
# or arbitrary classes. In this case the json library falls back to call
# Object#to_json, which is the same as #to_s.to_json.
#
-# It's possible to extend JSON to support serialization of arbitrary classes by
+# It's possible to add JSON support serialization to arbitrary classes by
# simply implementing a more specialized version of the #to_json method, that
-# should return a JSON object (a hash converted to JSON with #to_json)
-# like this (don't forget the *a for all the arguments):
+# should return a JSON object (a hash converted to JSON with #to_json) like
+# this (don't forget the *a for all the arguments):
#
# class Range
# def to_json(*a)
@@ -159,15 +161,15 @@ require 'json/common'
# end
# end
#
-# The hash key 'json_class' is the class, that will be asked to deserialize the
+# The hash key 'json_class' is the class, that will be asked to deserialise the
# JSON representation later. In this case it's 'Range', but any namespace of
# the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
-# used to store the necessary data to configure the object to be deserialized.
+# used to store the necessary data to configure the object to be deserialised.
#
# If a the key 'json_class' is found in a JSON object, the JSON parser checks
# if the given class responds to the json_create class method. If so, it is
# called with the JSON object converted to a Ruby hash. So a range can
-# be deserialized by implementing Range.json_create like this:
+# be deserialised by implementing Range.json_create like this:
#
# class Range
# def self.json_create(o)
@@ -175,7 +177,7 @@ require 'json/common'
# end
# end
#
-# Now it possible to serialize/deserialize ranges as well:
+# Now it possible to serialise/deserialise ranges as well:
#
# json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
# # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
diff --git a/lib/json/add/core.rb b/lib/json/add/core.rb
new file mode 100644
index 0000000000..630ed6e4b7
--- /dev/null
+++ b/lib/json/add/core.rb
@@ -0,0 +1,120 @@
+# This file contains implementations of ruby core's custom objects for
+# serialisation/deserialisation.
+
+unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
+ ::JSON::JSON_LOADED
+ require 'json'
+end
+require 'date'
+
+class Time
+ def self.json_create(object)
+ at(*object.values_at('s', 'u'))
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name.to_s,
+ 's' => tv_sec,
+ 'u' => tv_usec,
+ }.to_json(*args)
+ end
+end
+
+class Date
+ def self.json_create(object)
+ civil(*object.values_at('y', 'm', 'd', 'sg'))
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name.to_s,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'sg' => @sg,
+ }.to_json(*args)
+ end
+end
+
+class DateTime
+ def self.json_create(object)
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
+ of_a, of_b = object['of'].split('/')
+ args << Rational(of_a.to_i, of_b.to_i)
+ args << object['sg']
+ civil(*args)
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name.to_s,
+ 'y' => year,
+ 'm' => month,
+ 'd' => day,
+ 'H' => hour,
+ 'M' => min,
+ 'S' => sec,
+ 'of' => offset.to_s,
+ 'sg' => @sg,
+ }.to_json(*args)
+ end
+end
+
+class Range
+ def self.json_create(object)
+ new(*object['a'])
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name.to_s,
+ 'a' => [ first, last, exclude_end? ]
+ }.to_json(*args)
+ end
+end
+
+class Struct
+ def self.json_create(object)
+ new(*object['v'])
+ end
+
+ def to_json(*args)
+ klass = self.class.name.to_s
+ klass.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ {
+ 'json_class' => klass,
+ 'v' => values,
+ }.to_json(*args)
+ end
+end
+
+class Exception
+ def self.json_create(object)
+ result = new(object['m'])
+ result.set_backtrace object['b']
+ result
+ end
+
+ def to_json(*args)
+ {
+ 'json_class' => self.class.name.to_s,
+ 'm' => message,
+ 'b' => backtrace,
+ }.to_json(*args)
+ end
+end
+
+class Regexp
+ def self.json_create(object)
+ new(object['s'], object['o'])
+ end
+
+ def to_json(*)
+ {
+ 'json_class' => self.class.name.to_s,
+ 'o' => options,
+ 's' => source,
+ }.to_json
+ end
+end
diff --git a/lib/json/add/rails.rb b/lib/json/add/rails.rb
new file mode 100644
index 0000000000..e86ed1aab9
--- /dev/null
+++ b/lib/json/add/rails.rb
@@ -0,0 +1,58 @@
+# This file contains implementations of rails custom objects for
+# serialisation/deserialisation.
+
+unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
+ ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class Object
+ def self.json_create(object)
+ obj = new
+ for key, value in object
+ next if key == 'json_class'
+ instance_variable_set "@#{key}", value
+ end
+ obj
+ end
+
+ def to_json(*a)
+ result = {
+ 'json_class' => self.class.name
+ }
+ instance_variables.inject(result) do |r, name|
+ r[name[1..-1]] = instance_variable_get name
+ r
+ end
+ result.to_json(*a)
+ end
+end
+
+class Symbol
+ def to_json(*a)
+ to_s.to_json(*a)
+ end
+end
+
+module Enumerable
+ def to_json(*a)
+ to_a.to_json(*a)
+ end
+end
+
+# class Regexp
+# def to_json(*)
+# inspect
+# end
+# end
+#
+# The above rails definition has some problems:
+#
+# 1. { 'foo' => /bar/ }.to_json # => "{foo: /bar/}"
+# This isn't valid JSON, because the regular expression syntax is not
+# defined in RFC 4627. (And unquoted strings are disallowed there, too.)
+# Though it is valid Javascript.
+#
+# 2. { 'foo' => /bar/mix }.to_json # => "{foo: /bar/mix}"
+# This isn't even valid Javascript.
+