diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-11-30 12:08:46 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-11-30 12:08:46 +0000 |
commit | a049c43c65822b8736791d71c3d51dcca0f75cfa (patch) | |
tree | 06b51542816c4261d2b45e4f5f7077635c83bbc2 /lib | |
parent | e46a61775933d1ce9207fde4422ad536fed4846a (diff) | |
download | ruby-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.rb | 26 | ||||
-rw-r--r-- | lib/json/add/core.rb | 120 | ||||
-rw-r--r-- | lib/json/add/rails.rb | 58 |
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. + |