apimatic_core 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +28 -15
- data/lib/apimatic-core/api_call.rb +0 -1
- data/lib/apimatic-core/configurations/global_configuration.rb +0 -14
- data/lib/apimatic-core/exceptions/any_of_validation_exception.rb +13 -0
- data/lib/apimatic-core/exceptions/one_of_validation_exception.rb +13 -0
- data/lib/apimatic-core/request_builder.rb +0 -26
- data/lib/apimatic-core/response_handler.rb +4 -19
- data/lib/apimatic-core/types/parameter.rb +11 -22
- data/lib/apimatic-core/types/union_types/any_of.rb +90 -0
- data/lib/apimatic-core/types/union_types/leaf_type.rb +298 -0
- data/lib/apimatic-core/types/union_types/one_of.rb +90 -0
- data/lib/apimatic-core/types/union_types/union_type_context.rb +30 -0
- data/lib/apimatic-core/utilities/api_helper.rb +60 -156
- data/lib/apimatic-core/utilities/date_time_helper.rb +54 -7
- data/lib/apimatic-core/utilities/union_type_helper.rb +298 -0
- data/lib/apimatic_core.rb +8 -0
- metadata +11 -4
@@ -0,0 +1,298 @@
|
|
1
|
+
module CoreLibrary
|
2
|
+
# Represents a leaf type in a UnionType
|
3
|
+
class LeafType < UnionType
|
4
|
+
attr_reader :type_to_match
|
5
|
+
|
6
|
+
# Initializes a new instance of LeafType
|
7
|
+
# @param type_to_match [Class] The type to match against
|
8
|
+
# @param union_type_context [UnionTypeContext] The UnionTypeContext associated with the leaf type
|
9
|
+
def initialize(type_to_match, union_type_context = UnionTypeContext.new)
|
10
|
+
super(nil, union_type_context)
|
11
|
+
@type_to_match = type_to_match
|
12
|
+
end
|
13
|
+
|
14
|
+
# Validates a value against the leaf type
|
15
|
+
# @param value [Object] The value to validate
|
16
|
+
# @return [LeafType] The current LeafType object
|
17
|
+
def validate(value)
|
18
|
+
context = @union_type_context
|
19
|
+
|
20
|
+
@is_valid = if value.nil?
|
21
|
+
context.nullable_or_optional?
|
22
|
+
else
|
23
|
+
validate_value_against_case(value, context)
|
24
|
+
end
|
25
|
+
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize(value)
|
30
|
+
return nil if value.nil?
|
31
|
+
|
32
|
+
serialize_value_against_case(value, @union_type_context)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Deserializes a value based on the leaf type
|
36
|
+
# @param value [Object] The value to deserialize
|
37
|
+
# @param should_symbolize [Boolean] Indicates whether the deserialized value should be symbolized.
|
38
|
+
# @return [Object, nil] The deserialized value or nil if the input value is nil
|
39
|
+
def deserialize(value, should_symbolize: false)
|
40
|
+
return nil if value.nil?
|
41
|
+
|
42
|
+
deserialize_value_against_case(value, @union_type_context, should_symbolize: should_symbolize)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate_value_against_case(value, context)
|
48
|
+
if context.is_array && context.is_dict && context.is_array_of_dict
|
49
|
+
validate_array_of_dict_case(value)
|
50
|
+
elsif context.is_array && context.is_dict
|
51
|
+
validate_dict_of_array_case(value)
|
52
|
+
elsif context.is_array
|
53
|
+
validate_array_case(value)
|
54
|
+
elsif context.is_dict
|
55
|
+
validate_dict_case(value)
|
56
|
+
else
|
57
|
+
validate_simple_case(value)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_dict_case(dict_value)
|
62
|
+
return false unless dict_value.instance_of?(Hash)
|
63
|
+
|
64
|
+
dict_value.each do |_key, value|
|
65
|
+
is_valid = validate_simple_case(value)
|
66
|
+
return false unless is_valid
|
67
|
+
end
|
68
|
+
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_dict_of_array_case(dict_value)
|
73
|
+
return false unless dict_value.instance_of?(Hash)
|
74
|
+
|
75
|
+
dict_value.each do |_key, value|
|
76
|
+
is_valid = validate_array_case(value)
|
77
|
+
return false unless is_valid
|
78
|
+
end
|
79
|
+
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_array_case(array_value)
|
84
|
+
return false unless array_value.instance_of?(Array)
|
85
|
+
|
86
|
+
array_value.each do |item|
|
87
|
+
is_valid = validate_simple_case(item)
|
88
|
+
return false unless is_valid
|
89
|
+
end
|
90
|
+
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate_array_of_dict_case(array_value)
|
95
|
+
return false unless array_value.instance_of?(Array)
|
96
|
+
|
97
|
+
array_value.each do |item|
|
98
|
+
is_valid = validate_dict_case(item)
|
99
|
+
return false unless is_valid
|
100
|
+
end
|
101
|
+
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def validate_simple_case(value)
|
106
|
+
context = @union_type_context
|
107
|
+
|
108
|
+
if value.nil? || context.nullable_or_optional?
|
109
|
+
true
|
110
|
+
elsif value.nil? || value.instance_of?(Array)
|
111
|
+
false
|
112
|
+
else
|
113
|
+
validate_value(value, context)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate_value(value, context)
|
118
|
+
if @type_to_match == DateTime
|
119
|
+
dt_string = if value.instance_of?(DateTime) && context.date_time_converter
|
120
|
+
context.date_time_converter.call(value)
|
121
|
+
else
|
122
|
+
value
|
123
|
+
end
|
124
|
+
|
125
|
+
DateTimeHelper.valid_datetime?(context.date_time_format, dt_string)
|
126
|
+
elsif @type_to_match == Date
|
127
|
+
DateTimeHelper.valid_date?(value)
|
128
|
+
else
|
129
|
+
validate_value_with_discriminator(value, context)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def validate_value_with_discriminator(value, context)
|
134
|
+
discriminator = context.discriminator
|
135
|
+
discriminator_value = context.discriminator_value
|
136
|
+
|
137
|
+
if discriminator && discriminator_value
|
138
|
+
validate_with_discriminator(discriminator, discriminator_value, value)
|
139
|
+
elsif @type_to_match.respond_to?(:validate)
|
140
|
+
@type_to_match.validate(value)
|
141
|
+
else
|
142
|
+
value.instance_of?(@type_to_match)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def validate_with_discriminator(discriminator, discriminator_value, value)
|
147
|
+
return false unless value.instance_of?(Hash) && value[discriminator] == discriminator_value
|
148
|
+
|
149
|
+
if @type_to_match.respond_to?(:validate)
|
150
|
+
@type_to_match.validate(value)
|
151
|
+
else
|
152
|
+
value.instance_of?(@type_to_match)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def serialize_value_against_case(value, context)
|
157
|
+
if context.is_array && context.is_dict && context.is_array_of_dict
|
158
|
+
serialize_array_of_dict_case(value)
|
159
|
+
elsif context.is_array && context.is_dict
|
160
|
+
serialize_dict_of_array_case(value)
|
161
|
+
elsif context.is_array
|
162
|
+
serialize_array_case(value)
|
163
|
+
elsif context.is_dict
|
164
|
+
serialize_dict_case(value)
|
165
|
+
else
|
166
|
+
serialize_simple_case(value)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def serialize_dict_case(dict_value)
|
171
|
+
serialized_value = {}
|
172
|
+
|
173
|
+
dict_value.each do |key, value|
|
174
|
+
result_value = serialize_simple_case(value)
|
175
|
+
serialized_value[key] = result_value
|
176
|
+
end
|
177
|
+
|
178
|
+
serialized_value
|
179
|
+
end
|
180
|
+
|
181
|
+
def serialize_dict_of_array_case(dict_value)
|
182
|
+
serialized_value = {}
|
183
|
+
|
184
|
+
dict_value.each do |key, value|
|
185
|
+
result_value = serialize_array_case(value)
|
186
|
+
serialized_value[key] = result_value
|
187
|
+
end
|
188
|
+
|
189
|
+
serialized_value
|
190
|
+
end
|
191
|
+
|
192
|
+
def serialize_array_case(array_value)
|
193
|
+
serialized_value = []
|
194
|
+
|
195
|
+
array_value.each do |item|
|
196
|
+
result_value = serialize_simple_case(item)
|
197
|
+
serialized_value << result_value
|
198
|
+
end
|
199
|
+
|
200
|
+
serialized_value
|
201
|
+
end
|
202
|
+
|
203
|
+
def serialize_array_of_dict_case(array_value)
|
204
|
+
serialized_value = []
|
205
|
+
|
206
|
+
array_value.each do |item|
|
207
|
+
result_value = serialize_dict_case(item)
|
208
|
+
serialized_value << result_value
|
209
|
+
end
|
210
|
+
|
211
|
+
serialized_value
|
212
|
+
end
|
213
|
+
|
214
|
+
def serialize_simple_case(value)
|
215
|
+
case @union_type_context.date_time_format
|
216
|
+
when DateTimeFormat::HTTP_DATE_TIME
|
217
|
+
return DateTimeHelper.to_rfc1123(value)
|
218
|
+
when DateTimeFormat::RFC3339_DATE_TIME
|
219
|
+
return DateTimeHelper.to_rfc3339(value)
|
220
|
+
when DateTimeFormat::UNIX_DATE_TIME
|
221
|
+
return DateTimeHelper.to_unix(value)
|
222
|
+
end
|
223
|
+
|
224
|
+
value
|
225
|
+
end
|
226
|
+
|
227
|
+
def deserialize_value_against_case(value, context, should_symbolize: false)
|
228
|
+
if context.is_array && context.is_dict && context.is_array_of_dict
|
229
|
+
deserialize_array_of_dict_case(value, should_symbolize: should_symbolize)
|
230
|
+
elsif context.is_array && context.is_dict
|
231
|
+
deserialize_dict_of_array_case(value, should_symbolize: should_symbolize)
|
232
|
+
elsif context.is_array
|
233
|
+
deserialize_array_case(value, should_symbolize: should_symbolize)
|
234
|
+
elsif context.is_dict
|
235
|
+
deserialize_dict_case(value, should_symbolize: should_symbolize)
|
236
|
+
else
|
237
|
+
deserialize_simple_case(value, should_symbolize: should_symbolize)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def deserialize_dict_case(dict_value, should_symbolize: false)
|
242
|
+
deserialized_value = {}
|
243
|
+
|
244
|
+
dict_value.each do |key, value|
|
245
|
+
result_value = deserialize_simple_case(value, should_symbolize: should_symbolize)
|
246
|
+
deserialized_value[key] = result_value
|
247
|
+
end
|
248
|
+
|
249
|
+
deserialized_value
|
250
|
+
end
|
251
|
+
|
252
|
+
def deserialize_dict_of_array_case(dict_value, should_symbolize: false)
|
253
|
+
deserialized_value = {}
|
254
|
+
|
255
|
+
dict_value.each do |key, value|
|
256
|
+
result_value = deserialize_array_case(value, should_symbolize: should_symbolize)
|
257
|
+
deserialized_value[key] = result_value
|
258
|
+
end
|
259
|
+
|
260
|
+
deserialized_value
|
261
|
+
end
|
262
|
+
|
263
|
+
def deserialize_array_case(array_value, should_symbolize: false)
|
264
|
+
deserialized_value = []
|
265
|
+
|
266
|
+
array_value.each do |item|
|
267
|
+
result_value = deserialize_simple_case(item, should_symbolize: should_symbolize)
|
268
|
+
deserialized_value << result_value
|
269
|
+
end
|
270
|
+
|
271
|
+
deserialized_value
|
272
|
+
end
|
273
|
+
|
274
|
+
def deserialize_array_of_dict_case(array_value, should_symbolize: false)
|
275
|
+
deserialized_value = []
|
276
|
+
|
277
|
+
array_value.each do |item|
|
278
|
+
result_value = deserialize_dict_case(item, should_symbolize: should_symbolize)
|
279
|
+
deserialized_value << result_value
|
280
|
+
end
|
281
|
+
|
282
|
+
deserialized_value
|
283
|
+
end
|
284
|
+
|
285
|
+
def deserialize_simple_case(value, should_symbolize: false)
|
286
|
+
if @type_to_match.respond_to?(:from_hash)
|
287
|
+
@type_to_match.from_hash(value)
|
288
|
+
elsif @type_to_match == Date
|
289
|
+
ApiHelper.date_deserializer(value, false, should_symbolize: should_symbolize)
|
290
|
+
elsif @type_to_match == DateTime
|
291
|
+
ApiHelper.deserialize_datetime(value, @union_type_context.date_time_format,
|
292
|
+
false, should_symbolize: should_symbolize)
|
293
|
+
else
|
294
|
+
value
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module CoreLibrary
|
2
|
+
# Represents the OneOf union type in the core library
|
3
|
+
class OneOf < UnionType
|
4
|
+
# Initializes a new instance of OneOf
|
5
|
+
# @param union_types [Array] The array of nested union types
|
6
|
+
# @param union_type_context [UnionTypeContext] The context for the union type
|
7
|
+
def initialize(union_types, union_type_context = UnionTypeContext.new)
|
8
|
+
super(union_types, union_type_context)
|
9
|
+
@collection_cases = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# Validates a value against the OneOf union type
|
13
|
+
# @param value [Object] The value to validate
|
14
|
+
# @return [OneOf] The validated OneOf object
|
15
|
+
def validate(value)
|
16
|
+
context = @union_type_context
|
17
|
+
UnionTypeHelper.update_nested_flag_for_union_types(@union_types)
|
18
|
+
is_optional_or_nullable = UnionTypeHelper.optional_or_nullable_case?(
|
19
|
+
context,
|
20
|
+
@union_types.map(&:union_type_context)
|
21
|
+
)
|
22
|
+
|
23
|
+
if value.nil? && is_optional_or_nullable
|
24
|
+
@is_valid = true
|
25
|
+
return self
|
26
|
+
end
|
27
|
+
|
28
|
+
if value.nil?
|
29
|
+
@is_valid = false
|
30
|
+
@error_messages = UnionTypeHelper.process_errors(value, @union_types, @error_messages,
|
31
|
+
union_type_context.is_nested, true)
|
32
|
+
end
|
33
|
+
|
34
|
+
_validate_value_against_case(value, context)
|
35
|
+
|
36
|
+
unless @is_valid
|
37
|
+
@error_messages = UnionTypeHelper.process_errors(value, @union_types, @error_messages,
|
38
|
+
union_type_context.is_nested, true)
|
39
|
+
end
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# Serializes a given value.
|
45
|
+
# @param value [Object] The value to be serialized.
|
46
|
+
# @return [Object, nil] The serialized representation of the value, or nil if the value is nil.
|
47
|
+
def serialize(value)
|
48
|
+
return nil if value.nil?
|
49
|
+
|
50
|
+
UnionTypeHelper.serialize_value(
|
51
|
+
value,
|
52
|
+
@union_type_context,
|
53
|
+
@collection_cases,
|
54
|
+
@union_types
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Deserializes a value based on the OneOf union type
|
59
|
+
# @param value [Object] The value to deserialize
|
60
|
+
# @param should_symbolize [Boolean] Indicates whether the deserialized value should be symbolized.
|
61
|
+
# @return [Object, nil] The deserialized value, or nil if the input value is nil
|
62
|
+
def deserialize(value, should_symbolize: false)
|
63
|
+
return nil if value.nil?
|
64
|
+
|
65
|
+
UnionTypeHelper.deserialize_value(value, @union_type_context, @collection_cases,
|
66
|
+
@union_types, should_symbolize: should_symbolize)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Validates a value against the appropriate case of the OneOf union type
|
72
|
+
# @param value [Object] The value to validate
|
73
|
+
# @param context [UnionTypeContext] The context for the union type
|
74
|
+
def _validate_value_against_case(value, context)
|
75
|
+
if context.is_array && context.is_dict && context.is_array_of_dict
|
76
|
+
@is_valid, @collection_cases = UnionTypeHelper.validate_array_of_dict_case(@union_types, value,
|
77
|
+
true)
|
78
|
+
elsif context.is_array && context.is_dict
|
79
|
+
@is_valid, @collection_cases = UnionTypeHelper.validate_dict_of_array_case(@union_types, value,
|
80
|
+
true)
|
81
|
+
elsif context.is_array
|
82
|
+
@is_valid, @collection_cases = UnionTypeHelper.validate_array_case(@union_types, value, true)
|
83
|
+
elsif context.is_dict
|
84
|
+
@is_valid, @collection_cases = UnionTypeHelper.validate_dict_case(@union_types, value, true)
|
85
|
+
else
|
86
|
+
@is_valid = UnionTypeHelper.get_matched_count(value, @union_types, true) == 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module CoreLibrary
|
2
|
+
# Represents the context for a UnionType
|
3
|
+
class UnionTypeContext
|
4
|
+
attr_reader :is_array, :is_dict, :is_array_of_dict, :is_optional,
|
5
|
+
:is_nullable, :date_time_format, :date_time_converter
|
6
|
+
|
7
|
+
attr_accessor :is_nested, :discriminator, :discriminator_value
|
8
|
+
|
9
|
+
# Initializes a new instance of UnionTypeContext
|
10
|
+
def initialize(is_array: false, is_dict: false, is_array_of_dict: false, is_optional: false, is_nullable: false,
|
11
|
+
discriminator: nil, discriminator_value: nil, date_time_format: nil, date_time_converter: nil)
|
12
|
+
@is_array = is_array
|
13
|
+
@is_dict = is_dict
|
14
|
+
@is_array_of_dict = is_array_of_dict
|
15
|
+
@is_optional = is_optional
|
16
|
+
@is_nullable = is_nullable
|
17
|
+
@discriminator = discriminator
|
18
|
+
@discriminator_value = discriminator_value
|
19
|
+
@date_time_format = date_time_format
|
20
|
+
@date_time_converter = date_time_converter
|
21
|
+
@is_nested = false
|
22
|
+
end
|
23
|
+
|
24
|
+
# Determines if the UnionTypeContext is nullable or optional
|
25
|
+
# @return [Boolean] True if the context is nullable or optional, false otherwise
|
26
|
+
def nullable_or_optional?
|
27
|
+
@is_nullable || @is_optional
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -72,9 +72,7 @@ module CoreLibrary
|
|
72
72
|
# Deserializer to use when the type of response is not known beforehand.
|
73
73
|
# @param response The response received.
|
74
74
|
def self.dynamic_deserializer(response, should_symbolize)
|
75
|
-
|
76
|
-
response.to_s.strip.empty?
|
77
|
-
decoded
|
75
|
+
json_deserialize(response, should_symbolize) unless response.nil? || response.to_s.strip.empty?
|
78
76
|
end
|
79
77
|
|
80
78
|
# Deserializes response to a known custom model type.
|
@@ -228,19 +226,73 @@ module CoreLibrary
|
|
228
226
|
protocol + query + parameters
|
229
227
|
end
|
230
228
|
|
231
|
-
#
|
229
|
+
# Deserialize the response based on the provided union_type.
|
230
|
+
# @param [UnionType] union_type The union type to validate and deserialize the response.
|
231
|
+
# @param [Object] response The response object to be deserialized.
|
232
|
+
# @param [Boolean] should_deserialize Flag indicating whether the response should be deserialized.
|
233
|
+
# Default is true.
|
234
|
+
# @return [Object] The deserialized response based on the union_type.
|
235
|
+
def self.deserialize_union_type(union_type, response, should_symbolize = false, should_deserialize = false)
|
236
|
+
response = ApiHelper.json_deserialize(response, false, true) if should_deserialize
|
237
|
+
|
238
|
+
union_type_result = union_type.validate(response)
|
239
|
+
|
240
|
+
union_type_result.deserialize(response, should_symbolize: should_symbolize)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Applies a primitive type parser to deserialize a value.
|
244
|
+
# @param [String] value The value to be parsed.
|
245
|
+
# @return [Integer, Float, Boolean, String] The deserialized value,
|
246
|
+
# which can be an Integer, Float, Boolean, or String.
|
247
|
+
def self.apply_primitive_type_parser(value)
|
248
|
+
# Attempt to deserialize as Integer
|
249
|
+
return value.to_i if value.match?(/^\d+$/)
|
250
|
+
|
251
|
+
# Attempt to deserialize as Float
|
252
|
+
return value.to_f if value.match?(/^\d+(\.\d+)?$/)
|
253
|
+
|
254
|
+
# Attempt to deserialize as Boolean
|
255
|
+
return true if value.downcase == 'true'
|
256
|
+
return false if value.downcase == 'false'
|
257
|
+
|
258
|
+
# Default: return the original string
|
259
|
+
value
|
260
|
+
end
|
261
|
+
|
262
|
+
# Checks if a value or all values in a nested structure satisfy a given type condition.
|
263
|
+
# @param [Object] value The value or nested structure to be checked.
|
264
|
+
# @param [Proc] type_callable A callable object that defines the type condition.
|
265
|
+
# @return [Boolean] Returns true if the value or all values in the
|
266
|
+
# structure satisfy the type condition, false otherwise.
|
267
|
+
def self.valid_type?(value, type_callable)
|
268
|
+
if value.is_a?(Array)
|
269
|
+
value.all? { |item| valid_type?(item, type_callable) }
|
270
|
+
elsif value.is_a?(Hash)
|
271
|
+
value.values.all? { |item| valid_type?(item, type_callable) }
|
272
|
+
else
|
273
|
+
!value.nil? && type_callable.call(value)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# Parses a JSON string.
|
232
278
|
# @param [String] json A JSON string.
|
233
|
-
#
|
234
|
-
|
279
|
+
# @param [Boolean] should_symbolize Determines whether the keys should be symbolized.
|
280
|
+
# If set to true, the keys will be converted to symbols. Defaults to false.
|
281
|
+
# @param [Boolean] allow_primitive_type_parsing Determines whether to allow parsing of primitive types.
|
282
|
+
# If set to true, the method will attempt to parse primitive types like numbers and booleans. Defaults to false.
|
283
|
+
# @return [Hash, Array, nil] The parsed JSON object, or nil if the input string is nil.
|
284
|
+
# @raise [TypeError] if the server responds with invalid JSON and primitive type parsing is not allowed.
|
285
|
+
def self.json_deserialize(json, should_symbolize = false, allow_primitive_type_parsing = false)
|
235
286
|
return if json.nil?
|
236
287
|
|
237
288
|
begin
|
238
289
|
JSON.parse(json, symbolize_names: should_symbolize)
|
239
290
|
rescue StandardError
|
240
|
-
raise TypeError, 'Server responded with invalid JSON.'
|
291
|
+
raise TypeError, 'Server responded with invalid JSON.' unless allow_primitive_type_parsing
|
292
|
+
|
293
|
+
ApiHelper.apply_primitive_type_parser(json)
|
241
294
|
end
|
242
295
|
end
|
243
|
-
# rubocop:enable Style/OptionalBooleanParameter
|
244
296
|
|
245
297
|
# Parses JSON string.
|
246
298
|
# @param [object] obj The object to serialize.
|
@@ -383,154 +435,6 @@ module CoreLibrary
|
|
383
435
|
val
|
384
436
|
end
|
385
437
|
|
386
|
-
# Deserialize the value against the template (group of types).
|
387
|
-
# @param [String] value The value to be deserialized.
|
388
|
-
# @param [String] template The type-combination group for which the value will be mapped (oneOf(Integer, String)).
|
389
|
-
def self.deserialize(template, value, sdk_module, should_symbolize)
|
390
|
-
decoded = json_deserialize(value, should_symbolize)
|
391
|
-
map_types(decoded, template, sdk_module: sdk_module)
|
392
|
-
end
|
393
|
-
|
394
|
-
# Validates and processes the value against the template(group of types).
|
395
|
-
# @param [String] value The value to be mapped against the template.
|
396
|
-
# @param [String] template The parameter indicates the group of types (oneOf(Integer, String)).
|
397
|
-
# @param [String] group_name The parameter indicates the group (oneOf|anyOf).
|
398
|
-
def self.map_types(value, template, group_name: nil, sdk_module: nil)
|
399
|
-
result_value = nil
|
400
|
-
matches = 0
|
401
|
-
types = []
|
402
|
-
group_name = template.partition('(').first if group_name.nil? && template.match?(/anyOf|oneOf/)
|
403
|
-
|
404
|
-
return if value.nil?
|
405
|
-
|
406
|
-
if template.end_with?('{}') || template.end_with?('[]')
|
407
|
-
types = template.split(group_name, 2).last.gsub(/\s+/, '').split
|
408
|
-
else
|
409
|
-
template = template.split(group_name, 2).last.delete_prefix('(').delete_suffix(')')
|
410
|
-
types = template.scan(/(anyOf|oneOf)[(]([^[)]]*)[)]/).flatten.combination(2).map { |a, b| "#{a}(#{b})" }
|
411
|
-
types.each { |t| template = template.gsub(", #{t}", '') }
|
412
|
-
types = template.gsub(/\s+/, '').split(',').push(*types)
|
413
|
-
end
|
414
|
-
types.each do |element|
|
415
|
-
if element.match?(/^(oneOf|anyOf)[(].*$/)
|
416
|
-
begin
|
417
|
-
result_value = map_types(value, element, matches)
|
418
|
-
matches += 1
|
419
|
-
rescue ValidationException
|
420
|
-
next
|
421
|
-
end
|
422
|
-
elsif element.end_with?('{}')
|
423
|
-
result_value, matches = map_hash_type(value, element, group_name, matches)
|
424
|
-
elsif element.end_with?('[]')
|
425
|
-
result_value, matches = map_array_type(value, element, group_name, matches)
|
426
|
-
else
|
427
|
-
begin
|
428
|
-
result_value, matches = map_type(value, element, group_name, matches, sdk_module)
|
429
|
-
rescue StandardError
|
430
|
-
next
|
431
|
-
end
|
432
|
-
end
|
433
|
-
break if group_name == 'anyOf' && matches == 1
|
434
|
-
end
|
435
|
-
raise ValidationException, "The value #{value} provided doesn't validate against the schema #{template}" unless
|
436
|
-
matches == 1
|
437
|
-
|
438
|
-
value = result_value unless result_value.nil?
|
439
|
-
value
|
440
|
-
end
|
441
|
-
|
442
|
-
# Validates and processes the value against the [Hash] type.
|
443
|
-
# @param [String] value The value to be mapped against the type.
|
444
|
-
# @param [String] type The possible type of the value.
|
445
|
-
# @param [String] group_name The parameter indicates the group (oneOf|anyOf).
|
446
|
-
# @param [Integer] matches The parameter indicates the number of matches of value against types.
|
447
|
-
def self.map_hash_type(value, type, group_name, matches)
|
448
|
-
if value.instance_of? Hash
|
449
|
-
decoded = {}
|
450
|
-
value.each do |key, val|
|
451
|
-
type = type.chomp('{}').to_s
|
452
|
-
val = map_types(val, type, group_name: group_name)
|
453
|
-
decoded[key] = val unless type.empty?
|
454
|
-
rescue ValidationException
|
455
|
-
next
|
456
|
-
end
|
457
|
-
matches += 1 if decoded.length == value.length
|
458
|
-
value = decoded unless decoded.empty?
|
459
|
-
end
|
460
|
-
[value, matches]
|
461
|
-
end
|
462
|
-
|
463
|
-
# Validates and processes the value against the [Array] type.
|
464
|
-
# @param [String] value The value to be mapped against the type.
|
465
|
-
# @param [String] type The possible type of the value.
|
466
|
-
# @param [String] group_name The parameter indicates the group (oneOf|anyOf).
|
467
|
-
# @param [Integer] matches The parameter indicates the number of matches of value against types.
|
468
|
-
def self.map_array_type(value, type, group_name, matches)
|
469
|
-
if value.instance_of? Array
|
470
|
-
decoded = []
|
471
|
-
value.each do |val|
|
472
|
-
type = type.chomp('[]').to_s
|
473
|
-
val = map_types(val, type, group_name: group_name)
|
474
|
-
decoded.append(val) unless type.empty?
|
475
|
-
rescue ValidationException
|
476
|
-
next
|
477
|
-
end
|
478
|
-
matches += 1 if decoded.length == value.length
|
479
|
-
value = decoded unless decoded.empty?
|
480
|
-
end
|
481
|
-
[value, matches]
|
482
|
-
end
|
483
|
-
|
484
|
-
# Validates and processes the value against the type.
|
485
|
-
# @param [String] value The value to be mapped against the type.
|
486
|
-
# @param [String] type The possible type of the value.
|
487
|
-
# @param [String] _group_name The parameter indicates the group (oneOf|anyOf).
|
488
|
-
# @param [Integer] matches The parameter indicates the number of matches of value against types.
|
489
|
-
def self.map_type(value, type, _group_name, matches, sdk_module)
|
490
|
-
if sdk_module.constants.select do |c|
|
491
|
-
sdk_module.const_get(c).to_s == "#{sdk_module}::#{type}"
|
492
|
-
end.empty?
|
493
|
-
value, matches = map_data_type(value, type, matches)
|
494
|
-
else
|
495
|
-
value, matches = map_complex_type(value, type, matches, sdk_module)
|
496
|
-
end
|
497
|
-
[value, matches]
|
498
|
-
end
|
499
|
-
|
500
|
-
# Validates and processes the value against the complex types.
|
501
|
-
# @param [String] value The value to be mapped against the type.
|
502
|
-
# @param [String] type The possible type of the value.
|
503
|
-
# @param [Integer] matches The parameter indicates the number of matches of value against types.
|
504
|
-
def self.map_complex_type(value, type, matches, sdk_module)
|
505
|
-
# TODO: Add a nil check on sdk_module?
|
506
|
-
obj = sdk_module.const_get(type)
|
507
|
-
value = if obj.respond_to? 'from_hash'
|
508
|
-
obj.send('from_hash', value)
|
509
|
-
else
|
510
|
-
obj.constants.find { |k| obj.const_get(k) == value }
|
511
|
-
end
|
512
|
-
matches += 1 unless value.nil?
|
513
|
-
[value, matches]
|
514
|
-
end
|
515
|
-
|
516
|
-
# Validates and processes the value against the data types.
|
517
|
-
# @param [String] value The value to be mapped against the type.
|
518
|
-
# @param [String] element The possible type of the value.
|
519
|
-
# @param [Integer] matches The parameter indicates the number of matches of value against types.
|
520
|
-
def self.map_data_type(value, element, matches)
|
521
|
-
element = element.split('|').map { |x| Object.const_get x }
|
522
|
-
matches += 1 if element.all? { |x| data_types.include?(x) } &&
|
523
|
-
element.any? { |x| (value.instance_of? x) || (value.class.ancestors.include? x) }
|
524
|
-
[value, matches]
|
525
|
-
end
|
526
|
-
|
527
|
-
# Validates the value against the template(group of types).
|
528
|
-
# @param [String] value The value to be mapped against the type.
|
529
|
-
# @param [String] template The parameter indicates the group of types (oneOf(Integer, String)).
|
530
|
-
def self.validate_types(value, template, sdk_module, should_symbolize)
|
531
|
-
map_types(json_deserialize(value.to_json, should_symbolize), template, sdk_module: sdk_module)
|
532
|
-
end
|
533
|
-
|
534
438
|
# Get content-type depending on the value
|
535
439
|
# @param [Object] value The value for which the content-type is resolved.
|
536
440
|
def self.get_content_type(value)
|