blob: cc22dd86f7deeb9842ff9ec69c3e9e03c39db55d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
require 'date'
require 'time'
module Ievkit
class Serializer
def self.any_json
yajl || multi_json || json
end
def self.yajl
require 'yajl'
new(Yajl)
rescue LoadError
end
def self.json
require 'json'
new(JSON)
rescue LoadError
end
def self.multi_json
require 'multi_json'
new(MultiJson)
rescue LoadError
end
def self.message_pack
require 'msgpack'
new(MessagePack, :pack, :unpack)
rescue LoadError
end
def self.multipart
new(IevMultipart)
rescue LoadError
end
class IevMultipart
def self.dump(data)
data
end
def self.load(data)
data
end
end
# Public: Wraps a serialization format for Sawyer. Nested objects are
# prepared for serialization (such as changing Times to ISO 8601 Strings).
# Any serialization format that responds to #dump and #load will work.
def initialize(format, dump_method_name = nil, load_method_name = nil)
@format = format
@dump = @format.method(dump_method_name || :dump)
@load = @format.method(load_method_name || :load)
end
# Public: Encodes an Object (usually a Hash or Array of Hashes).
#
# data - Object to be encoded.
#
# Returns an encoded String.
def encode(data)
@dump.call(encode_object(data))
end
alias dump encode
# Public: Decodes a String into an Object (usually a Hash or Array of
# Hashes).
#
# data - An encoded String.
#
# Returns a decoded Object.
def decode(data)
return nil if data.nil? || data.strip.empty?
decode_object(@load.call(data))
end
alias load decode
def encode_object(data)
case data
when Hash then encode_hash(data)
when Array then data.map { |o| encode_object(o) }
else data
end
end
def encode_hash(hash)
hash.keys.each do |key|
case value = hash[key]
when Date then hash[key] = value.to_time.utc.xmlschema
when Time then hash[key] = value.utc.xmlschema
when Hash then hash[key] = encode_hash(value)
end
end
hash
end
def decode_object(data)
case data
when Hash then decode_hash(data)
when Array then data.map { |o| decode_object(o) }
else data
end
end
def decode_hash(hash)
hash.keys.each do |key|
hash[key.to_sym] = decode_hash_value(key, hash.delete(key))
end
hash
end
def decode_hash_value(key, value)
if time_field?(key, value)
if value.is_a?(String)
begin
Time.parse(value)
rescue ArgumentError
value
end
elsif value.is_a?(Integer) || value.is_a?(Float)
Time.at(value)
else
value
end
elsif value.is_a?(Hash)
decode_hash(value)
elsif value.is_a?(Array)
value.map { |o| decode_hash_value(key, o) }
else
value
end
end
def time_field?(key, value)
value && (key =~ /_(at|on)\z/ || key =~ /(\A|_)date\z/)
end
end
end
|