# This file contains implementations of ruby core's custom objects for
# serialisation/deserialisation.
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
require 'date'
# Symbol serialization/deserialization
class Symbol
# Stores class name (Symbol) with String representation of Symbol as a JSON string.
def to_json(*a)
{
JSON.create_id => self.class.name,
's' => to_s,
}.to_json(*a)
end
# Deserializes JSON string by converting the string value stored in the object to a Symbol
def self.json_create(o)
o['s'].to_sym
end
end
# Time serialization/deserialization
class Time
# Deserializes JSON string by converting time since epoch to Time
def self.json_create(object)
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
object['n'] = usec * 1000
end
if respond_to?(:tv_nsec)
at(*object.values_at('s', 'n'))
else
at(object['s'], object['n'] / 1000)
end
end
# Stores class name (Time) with number of seconds since epoch and number of microseconds for Time as JSON string
def to_json(*args)
{
JSON.create_id => self.class.name,
's' => tv_sec,
'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
}.to_json(*args)
end
end
# Date serialization/deserialization
class Date
# Deserializes JSON string by converting Julian year y, month m, day d and Day of Calendar Reform sg to Date.
def self.json_create(object)
civil(*object.values_at('y', 'm', 'd', 'sg'))
end
alias start sg unless method_defined?(:start)
# Stores class name (Date) with Julian year y, month m, day d and Day of Calendar Reform sg as JSON string
def to_json(*args)
{
JSON.create_id => self.class.name,
'y' => year,
'm' => month,
'd' => day,
'sg' => start,
}.to_json(*args)
end
end
# DateTime serialization/deserialization
class DateTime
# Deserializes JSON string by converting year y, month m, day d, hour H, minute M, second S, offset of and Day of Calendar Reform sg to DateTime.
def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/')
if of_b and of_b != '0'
args << Rational(of_a.to_i, of_b.to_i)
else
args << of_a
end
args << object['sg']
civil(*args)
end
alias start sg unless method_defined?(:start)
# Stores class name (DateTime) with Julian year y, month m, day d, hour H, minute M, second S, offset of and Day of Calendar Reform sg as JSON string
def to_json(*args)
{
JSON.create_id => self.class.name,
'y' => year,
'm' => month,
'd' => day,
'H' => hour,
'M' => min,
'S' => sec,
'of' => offset.to_s,
'sg' => start,
}.to_json(*args)
end
end
# Range serialization/deserialization
class Range
# Deserializes JSON string by constructing new Range object with arguments a serialized by to_json.
def self.json_create(object)
new(*object['a'])
end
# Stores class name (Range) with JSON array of arguments a which include first (integer), last (integer), and exclude_end? (boolean) as JSON string.
def to_json(*args)
{
JSON.create_id => self.class.name,
'a' => [ first, last, exclude_end? ]
}.to_json(*args)
end
end
# Struct serialization/deserialization
class Struct
# Deserializes JSON string by constructing new Struct object with values v serialized by to_json.
def self.json_create(object)
new(*object['v'])
end
# Stores class name (Struct) with Struct values v as a JSON string. Only named structs are supported.
def to_json(*args)
klass = self.class.name
klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
{
JSON.create_id => klass,
'v' => values,
}.to_json(*args)
end
end
# Exception serialization/deserialization
class Exception
# Deserializes JSON string by constructing new Exception object with message m and backtrace b serialized with to_json
def self.json_create(object)
result = new(object['m'])
result.set_backtrace object['b']
result
end
# Stores class name (Exception) with message m and backtrace array b as JSON string
def to_json(*args)
{
JSON.create_id => self.class.name,
'm' => message,
'b' => backtrace,
}.to_json(*args)
end
end
# Regexp serialization/deserialization
class Regexp
# Deserializes JSON string by constructing new Regexp object with source s (Regexp or String) and options o serialized by to_json
def self.json_create(object)
new(object['s'], object['o'])
end
# Stores class name (Regexp) with options o and source s (Regexp or String) as JSON string
def to_json(*)
{
JSON.create_id => self.class.name,
'o' => options,
's' => source,
}.to_json
end
end