@@ -9,6 +9,9 @@ module Serialize
9
9
GLOBALID_KEY = "__gid__"
10
10
SYMBOL_KEY = "__sym__"
11
11
SYMBOL_KEYS_KEY = "__sym_keys__"
12
+ TIMESTAMP_KEY = "__timestamp__"
13
+ TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%Z" # eg '2020-01-01 23:59:59.123456789+05:00'
14
+ OPEN_STRUCT_KEY = "__ostruct__"
12
15
13
16
module_function
14
17
@@ -55,10 +58,20 @@ def load_value(value)
55
58
if value . is_a? ( Array )
56
59
value . map { |item | load_value ( item ) }
57
60
elsif value . is_a? ( Hash )
58
- if value . size == 1 && value . key? ( GLOBALID_KEY )
59
- GlobalID ::Locator . locate ( value [ GLOBALID_KEY ] )
60
- elsif value . size == 1 && value . key? ( SYMBOL_KEY )
61
- value [ SYMBOL_KEY ] . to_sym
61
+ if value . size == 1
62
+ case value . keys . first # there's only 1 key
63
+ when GLOBALID_KEY
64
+ GlobalID ::Locator . locate ( value [ GLOBALID_KEY ] )
65
+ when SYMBOL_KEY
66
+ value [ SYMBOL_KEY ] . to_sym
67
+ when TIMESTAMP_KEY
68
+ timestamp_class_name , timestamp_s = value [ TIMESTAMP_KEY ]
69
+ timestamp_class = Object . const_get ( timestamp_class_name )
70
+ timestamp_class . strptime ( timestamp_s , TIMESTAMP_FORMAT )
71
+ when OPEN_STRUCT_KEY
72
+ ostruct_values = load_value ( value [ OPEN_STRUCT_KEY ] )
73
+ OpenStruct . new ( ostruct_values )
74
+ end
62
75
else
63
76
loaded_h = { }
64
77
sym_keys = value . fetch ( SYMBOL_KEYS_KEY , [ ] )
@@ -101,6 +114,11 @@ def dump_value(obj)
101
114
{ SYMBOL_KEY => obj . to_s }
102
115
elsif obj . respond_to? ( :to_gid_param )
103
116
{ GLOBALID_KEY => obj . to_gid_param }
117
+ elsif obj . is_a? ( Date ) || obj . is_a? ( Time )
118
+ # DateTime extends Date; for TimeWithZone, call `.utc` first.
119
+ { TIMESTAMP_KEY => [ obj . class . name , obj . strftime ( TIMESTAMP_FORMAT ) ] }
120
+ elsif obj . is_a? ( OpenStruct )
121
+ { OPEN_STRUCT_KEY => dump_value ( obj . to_h ) }
104
122
else
105
123
obj
106
124
end
0 commit comments