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
|
# File 'lib/typisch/serialization.rb', line 26
def serialize_to_jsonable(value, type=@type, existing_serializations={})
existing = existing_serializations[[type, value]]
return serialize_already_encountered_pair(value, type, existing) if existing
result = case type
when Type::Date
value.to_s
when Type::Time
value.iso8601
when Type::Sequence
if type.slice
slice = value[type.slice]
existing_serializations[[type, value]] = result = {
@type_tag_key => class_to_type_tag(value.class),
'range_start' => type.slice.begin
}
result['items'] = slice.map {|v| serialize_to_jsonable(v, type.type, existing_serializations)} if slice
result['total_items'] = value.length if type.total_length
result
else
result = existing_serializations[[type, value]] = []
value.each {|v| result << serialize_to_jsonable(v, type.type, existing_serializations)}
result
end
when Type::Tuple
result = existing_serializations[[type, value]] = []
type.types.zip(value).each {|t,v| result << serialize_to_jsonable(v,t,existing_serializations)}
result
when Type::Object
result = existing_serializations[[type, value]] = {@type_tag_key => class_to_type_tag(value.class)}
type.property_names_to_types.each do |prop_name, type|
result[prop_name.to_s] = serialize_to_jsonable(value.send(prop_name), type, existing_serializations)
end
result
when Type::Union
type = type.alternative_types.find {|t| t.shallow_check_type(value)}
raise SerializationError, "No types in union #{type} matched #{value.inspect}, could not serialize" unless type
serialize_to_jsonable(value, type, existing_serializations)
when Type::Constructor value
else
raise SerializationError, "Type #{type} not supported for serialization of #{value.inspect}"
end
result
end
|