json_schema-faker 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/VERSION +1 -1
- data/lib/json_schema/faker.rb +8 -275
- data/lib/json_schema/faker/strategy/simple.rb +311 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d295d3dfb065608b9af8b1bfcd4336ea16a7de1
|
4
|
+
data.tar.gz: 08969d39f4b51f7c4fc07fd0c7ec3cb9408d3995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a3360dae5813be93b1c4aa5ac9cdd04c5c1e7c5151d90529811d4e5530c48a022c187967a2d1e92bd5d395c3660c2978dedcabbd46114d7d37d7dc3823698e3
|
7
|
+
data.tar.gz: b07858fa1b121b06e58d3dd27342a76e2cc03e27fde3137ffd73d6a50c1ec15a9bf0c8cb9289795d08cd4f525ae86800022a1cfce2c456478f954bef5881d312
|
data/CHANGELOG.md
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/json_schema/faker.rb
CHANGED
@@ -10,293 +10,26 @@ module JsonSchema
|
|
10
10
|
module_function :logger, :logger=
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@schema = schema
|
13
|
+
module Strategy
|
14
|
+
require "json_schema/faker/strategy/simple"
|
15
|
+
end
|
17
16
|
|
17
|
+
def initialize(schema, options = {})
|
18
|
+
@schema = schema
|
18
19
|
@options = options
|
19
20
|
end
|
20
21
|
|
21
22
|
def generate(hint: nil)
|
22
|
-
|
23
|
+
strategy = @options[:strategy] || Strategy::Simple.new
|
23
24
|
|
24
25
|
Configuration.logger.debug "to generate against #{@schema.inspect_schema}" if Configuration.logger
|
26
|
+
|
27
|
+
generated = strategy.call(@schema, hint: nil, position: "")
|
25
28
|
Configuration.logger.debug "generated: #{generated.inspect}" if Configuration.logger
|
26
29
|
|
27
30
|
generated
|
28
31
|
end
|
29
32
|
|
30
33
|
protected
|
31
|
-
def _generate(schema, hint: nil, position:)
|
32
|
-
Configuration.logger.debug "current position: #{position}" if Configuration.logger
|
33
|
-
|
34
|
-
raise "here comes nil for schema at #{position}" unless schema
|
35
|
-
|
36
|
-
return schema.default if schema.default
|
37
|
-
|
38
|
-
if schema.not
|
39
|
-
hint ||= {}
|
40
|
-
# too difficult
|
41
|
-
# TODO: support one_of/any_of/all_of
|
42
|
-
hint[:not_have_keys] = schema.not.required if schema.not.required
|
43
|
-
hint[:not_be_values] = schema.not.enum if schema.not.enum
|
44
|
-
end
|
45
|
-
|
46
|
-
# TODO: should support the combinations of them
|
47
|
-
# http://json-schema.org/latest/json-schema-validation.html#anchor75
|
48
|
-
# Notes:
|
49
|
-
# one_of, any_of, all_of, properties and type is given default and never be nil
|
50
|
-
if !schema.one_of.empty?
|
51
|
-
generate_for_one_of(schema, hint: hint, position: position)
|
52
|
-
elsif !schema.any_of.empty?
|
53
|
-
generate_for_any_of(schema, hint: hint, position: position)
|
54
|
-
elsif !schema.all_of.empty?
|
55
|
-
generate_for_all_of(schema, hint: hint, position: position)
|
56
|
-
elsif schema.enum
|
57
|
-
generate_by_enum(schema, hint: hint, position: position)
|
58
|
-
elsif !schema.type.empty?
|
59
|
-
generate_by_type(schema, position: position)
|
60
|
-
else # consider as object
|
61
|
-
generate_for_object(schema, hint: hint, position: position)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def generate_for_one_of(schema, hint: nil, position:)
|
66
|
-
merged_schema = JsonSchema::Schema.new
|
67
|
-
merged_schema.copy_from(schema)
|
68
|
-
|
69
|
-
merged_schema.one_of = []
|
70
|
-
|
71
|
-
# TODO: treat rest as not
|
72
|
-
_generate(merge_schema(merged_schema, schema.one_of.first), hint: hint, position: "position/one_of[0]")
|
73
|
-
end
|
74
|
-
|
75
|
-
def generate_for_any_of(schema, hint: nil, position:)
|
76
|
-
merged_schema = JsonSchema::Schema.new
|
77
|
-
merged_schema.copy_from(schema)
|
78
|
-
|
79
|
-
merged_schema.any_of = []
|
80
|
-
|
81
|
-
_generate(merge_schema(merged_schema, schema.any_of.first), hint: hint, position: "position/any_of[0]")
|
82
|
-
end
|
83
|
-
|
84
|
-
def generate_for_all_of(schema, hint: nil, position:)
|
85
|
-
# deep_merge all_of
|
86
|
-
merged_schema = JsonSchema::Schema.new
|
87
|
-
merged_schema.copy_from(schema)
|
88
|
-
|
89
|
-
merged_schema.all_of = []
|
90
|
-
|
91
|
-
schema.all_of.each do |sub_schema|
|
92
|
-
merge_schema(merged_schema, sub_schema)
|
93
|
-
end
|
94
|
-
|
95
|
-
_generate(merged_schema, hint: hint, position: "position/all_of")
|
96
|
-
end
|
97
|
-
|
98
|
-
def generate_for_object(schema, hint: nil, position:)
|
99
|
-
# http://json-schema.org/latest/json-schema-validation.html#anchor53
|
100
|
-
if schema.required
|
101
|
-
keys = schema.required
|
102
|
-
required_length = schema.min_properties || keys.length
|
103
|
-
|
104
|
-
object = keys.each.with_object({}) do |key, hash|
|
105
|
-
hash[key] = _generate(schema.properties[key], hint: hint, position: "#{position}/#{key}") # TODO: pass hint
|
106
|
-
end
|
107
|
-
else
|
108
|
-
required_length = schema.min_properties || schema.max_properties || 0
|
109
|
-
|
110
|
-
keys = (schema.properties || {}).keys
|
111
|
-
keys -= (hint[:not_have_keys] || []) if hint
|
112
|
-
|
113
|
-
object = keys.first(required_length).each.with_object({}) do |key, hash|
|
114
|
-
hash[key] = _generate(schema.properties[key], hint: hint, position: "#{position}/#{key}") # TODO: pass hint
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# if length is not enough
|
119
|
-
if schema.additional_properties === false
|
120
|
-
(required_length - object.keys.length).times.each.with_object(object) do |i, hash|
|
121
|
-
if schema.pattern_properties.empty?
|
122
|
-
key = (schema.properties.keys - object.keys).first
|
123
|
-
hash[key] = _generate(schema.properties[key], hint: hint, position: "#{position}/#{key}")
|
124
|
-
else
|
125
|
-
name = Pxeger.new(schema.pattern_properties.keys.first).generate
|
126
|
-
hash[name] = _generate(schema.pattern_properties.values.first, hint: hint, position: "#{position}/#{name}")
|
127
|
-
end
|
128
|
-
end
|
129
|
-
else
|
130
|
-
# FIXME: key confilct with properties
|
131
|
-
(required_length - object.keys.length).times.each.with_object(object) do |i, hash|
|
132
|
-
hash[i.to_s] = i
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# consider dependency
|
137
|
-
depended_keys = object.keys & schema.dependencies.keys
|
138
|
-
|
139
|
-
# FIXME: circular dependency is not supported
|
140
|
-
depended_keys.each.with_object(object) do |key, hash|
|
141
|
-
dependency = schema.dependencies[key]
|
142
|
-
|
143
|
-
if dependency.is_a?(JsonSchema::Schema)
|
144
|
-
# too difficult we just merge
|
145
|
-
hash.update(_generate(schema.dependencies[key], hint: nil, position: "#{position}/dependencies/#{key}"))
|
146
|
-
else
|
147
|
-
dependency.each do |additional_key|
|
148
|
-
object[additional_key] = _generate(schema.properties[additional_key], hint: hint, position: "#{position}/dependencies/#{key}/#{additional_key}") unless object.has_key?(additional_key)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def generate_by_enum(schema, hint: nil, position:)
|
155
|
-
black_list = (hint ? hint[:not_be_values] : nil)
|
156
|
-
|
157
|
-
if Configuration.logger
|
158
|
-
Configuration.logger.info "generate by enum at #{position}"
|
159
|
-
Configuration.logger.debug schema.inspect_schema
|
160
|
-
Configuration.logger.debug "black list: #{black_list}" if black_list
|
161
|
-
end
|
162
|
-
|
163
|
-
if black_list
|
164
|
-
(schema.enum - black_list).first
|
165
|
-
else
|
166
|
-
schema.enum.first
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def generate_by_type(schema, hint: nil, position:)
|
171
|
-
if Configuration.logger
|
172
|
-
Configuration.logger.info "generate by type at #{position}"
|
173
|
-
Configuration.logger.debug schema.inspect_schema
|
174
|
-
end
|
175
|
-
|
176
|
-
# http://json-schema.org/latest/json-schema-core.html#anchor8
|
177
|
-
# TODO: use include? than first
|
178
|
-
case schema.type.first
|
179
|
-
when "array"
|
180
|
-
generate_for_array(schema, hint: hint, position: position)
|
181
|
-
when "boolean"
|
182
|
-
true
|
183
|
-
when "integer", "number"
|
184
|
-
generate_for_number(schema, hint: hint)
|
185
|
-
when "null"
|
186
|
-
nil
|
187
|
-
when "object"
|
188
|
-
# here comes object without properties
|
189
|
-
generate_for_object(schema, hint: hint, position: position)
|
190
|
-
when "string"
|
191
|
-
generate_for_string(schema, hint: hint)
|
192
|
-
else
|
193
|
-
raise "unknown type for #{schema.inspect_schema}"
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def generate_for_array(schema, hint: nil, position:)
|
198
|
-
# http://json-schema.org/latest/json-schema-validation.html#anchor36
|
199
|
-
# additionalItems items maxItems minItems uniqueItems
|
200
|
-
length = schema.min_items || 0
|
201
|
-
|
202
|
-
# if "items" is not present, or its value is an object, validation of the instance always succeeds, regardless of the value of "additionalItems";
|
203
|
-
# if the value of "additionalItems" is boolean value true or an object, validation of the instance always succeeds;
|
204
|
-
item = if (schema.items.nil? || schema.items.is_a?(JsonSchema::Schema)) || ( schema.additional_items === true || schema.additional_items.is_a?(JsonSchema::Schema))
|
205
|
-
length.times.map.with_index {|i| i }
|
206
|
-
else # in case schema.items is array and schema.additional_items is true
|
207
|
-
# if the value of "additionalItems" is boolean value false and the value of "items" is an array
|
208
|
-
# the instance is valid if its size is less than, or equal to, the size of "items".
|
209
|
-
raise "#{position}: item length(#{schema.items.length} is shorter than minItems(#{schema.min_items}))" unless schema.items.length <= length
|
210
|
-
|
211
|
-
# TODO: consider unique items
|
212
|
-
length.times.map.with_index {|i| _generate(schema.items[i], position: position + "[#{i}]") }
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def generate_for_number(schema, hint: nil)
|
217
|
-
# http://json-schema.org/latest/json-schema-validation.html#anchor13
|
218
|
-
# TODO: use hint[:not_be_values]
|
219
|
-
min = schema.min
|
220
|
-
max = schema.max
|
221
|
-
|
222
|
-
if schema.multiple_of
|
223
|
-
min = (min + schema.multiple_of - min % schema.multiple_of) if min
|
224
|
-
max = (max - max % schema.multiple_of) if max
|
225
|
-
end
|
226
|
-
|
227
|
-
delta = schema.multiple_of ? schema.multiple_of : 1
|
228
|
-
|
229
|
-
# TODO: more sophisticated caluculation
|
230
|
-
min, max = [ (min || (max ? max - delta * 2 : 0)), (max || (min ? min + delta * 2 : 0)) ]
|
231
|
-
|
232
|
-
# to get average of min and max can avoid exclusive*
|
233
|
-
if schema.type.first == "integer"
|
234
|
-
(min / delta + max / delta) / 2 * delta
|
235
|
-
else
|
236
|
-
(min + max) / 2.0
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def generate_for_string(schema, hint: nil)
|
241
|
-
# http://json-schema.org/latest/json-schema-validation.html#anchor25
|
242
|
-
# TODO: use hint[:not_be_values]
|
243
|
-
# TODO: support format
|
244
|
-
if schema.pattern
|
245
|
-
Pxeger.new(schema.pattern).generate
|
246
|
-
else
|
247
|
-
length = schema.min_length || 0
|
248
|
-
"a" * length
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def merge_schema(a, b)
|
253
|
-
# attr not supported now
|
254
|
-
# any_of: too difficult...
|
255
|
-
# enum/items: TODO: just get and of array
|
256
|
-
# not: too difficult (if `not` is not wrapped by all_of wrap it?)
|
257
|
-
# multiple_of TODO: least common multiple
|
258
|
-
# pattern: too difficult...
|
259
|
-
# format TODO: just override
|
260
|
-
|
261
|
-
# array properties
|
262
|
-
%i[ type one_of all_of ].each do |attr|
|
263
|
-
a.__send__("#{attr}=", a.__send__(attr) + b.__send__(attr))
|
264
|
-
end
|
265
|
-
a.required = (a.required ? a.required + b.required : b.required) if b.required
|
266
|
-
|
267
|
-
# object properties
|
268
|
-
# XXX: key conflict
|
269
|
-
%i[ properties pattern_properties dependencies ].each do |attr|
|
270
|
-
a.__send__("#{attr}=", a.__send__(attr).merge(b.__send__(attr)))
|
271
|
-
end
|
272
|
-
|
273
|
-
# override to stronger validation
|
274
|
-
%i[ additional_items additional_properties ].each do |attr|
|
275
|
-
a.__send__("#{attr}=", false) unless a.__send__(attr) && b.__send__(attr)
|
276
|
-
end
|
277
|
-
%i[ min_exclusive max_exclusive unique_items ].each do |attr|
|
278
|
-
a.__send__("#{attr}=", a.__send__(attr) & b.__send__(attr))
|
279
|
-
end
|
280
|
-
%i[ min min_length min_properties ].each do |attr|
|
281
|
-
if b.__send__(attr)
|
282
|
-
if a.__send__(attr)
|
283
|
-
a.__send__("#{attr}=", b.__send__(attr)) if b.__send__(attr) < a.__send__(attr)
|
284
|
-
else
|
285
|
-
a.__send__("#{attr}=", b.__send__(attr))
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
%i[ max max_length max_properties ].each do |attr|
|
290
|
-
if b.__send__(attr)
|
291
|
-
if a.__send__(attr)
|
292
|
-
a.__send__("#{attr}=", b.__send__(attr)) if b.__send__(attr) > a.__send__(attr)
|
293
|
-
else
|
294
|
-
a.__send__("#{attr}=", b.__send__(attr))
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
a
|
300
|
-
end
|
301
34
|
end
|
302
35
|
end
|
@@ -0,0 +1,311 @@
|
|
1
|
+
module JsonSchema::Faker::Strategy
|
2
|
+
class Simple
|
3
|
+
def call(schema, hint: nil, position:)
|
4
|
+
::JsonSchema::Faker::Configuration.logger.debug "current position: #{position}" if ::JsonSchema::Faker::Configuration.logger
|
5
|
+
|
6
|
+
raise "here comes nil for schema at #{position}" unless schema
|
7
|
+
|
8
|
+
# merge one_of/any_of/all_of
|
9
|
+
::JsonSchema::Faker::Configuration.logger.debug schema.inspect_schema if ::JsonSchema::Faker::Configuration.logger
|
10
|
+
schema = compact_schema(schema, position: position)
|
11
|
+
|
12
|
+
return schema.default if schema.default
|
13
|
+
|
14
|
+
if schema.not
|
15
|
+
hint ||= {}
|
16
|
+
# too difficult
|
17
|
+
# TODO: support one_of/any_of/all_of
|
18
|
+
hint[:not_have_keys] = schema.not.required if schema.not.required
|
19
|
+
hint[:not_be_values] = schema.not.enum if schema.not.enum
|
20
|
+
end
|
21
|
+
|
22
|
+
# http://json-schema.org/latest/json-schema-validation.html#anchor75
|
23
|
+
if schema.enum
|
24
|
+
generate_by_enum(schema, hint: hint, position: position)
|
25
|
+
else
|
26
|
+
generate_by_type(schema, hint: hint, position: position)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method :generate, :call
|
30
|
+
|
31
|
+
def generate_for_object(schema, hint: nil, position:)
|
32
|
+
# http://json-schema.org/latest/json-schema-validation.html#anchor53
|
33
|
+
if schema.required
|
34
|
+
keys = schema.required
|
35
|
+
required_length = schema.min_properties || keys.length
|
36
|
+
|
37
|
+
object = keys.each.with_object({}) do |key, hash|
|
38
|
+
hash[key] = generate(schema.properties[key], hint: hint, position: "#{position}/#{key}") # TODO: pass hint
|
39
|
+
end
|
40
|
+
else
|
41
|
+
required_length = schema.min_properties || schema.max_properties || 0
|
42
|
+
|
43
|
+
keys = (schema.properties || {}).keys
|
44
|
+
keys -= (hint[:not_have_keys] || []) if hint
|
45
|
+
|
46
|
+
object = keys.first(required_length).each.with_object({}) do |key, hash|
|
47
|
+
hash[key] = generate(schema.properties[key], hint: hint, position: "#{position}/#{key}") # TODO: pass hint
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# if length is not enough
|
52
|
+
if schema.additional_properties === false
|
53
|
+
(required_length - object.keys.length).times.each.with_object(object) do |i, hash|
|
54
|
+
if schema.pattern_properties.empty?
|
55
|
+
key = (schema.properties.keys - object.keys).first
|
56
|
+
hash[key] = generate(schema.properties[key], hint: hint, position: "#{position}/#{key}")
|
57
|
+
else
|
58
|
+
name = ::Pxeger.new(schema.pattern_properties.keys.first).generate
|
59
|
+
hash[name] = generate(schema.pattern_properties.values.first, hint: hint, position: "#{position}/#{name}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# FIXME: key confilct with properties
|
64
|
+
(required_length - object.keys.length).times.each.with_object(object) do |i, hash|
|
65
|
+
hash[i.to_s] = i
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# consider dependency
|
70
|
+
depended_keys = object.keys & schema.dependencies.keys
|
71
|
+
|
72
|
+
# FIXME: circular dependency is not supported
|
73
|
+
depended_keys.each.with_object(object) do |key, hash|
|
74
|
+
dependency = schema.dependencies[key]
|
75
|
+
|
76
|
+
if dependency.is_a?(::JsonSchema::Schema)
|
77
|
+
# too difficult we just merge
|
78
|
+
hash.update(generate(schema.dependencies[key], hint: nil, position: "#{position}/dependencies/#{key}"))
|
79
|
+
else
|
80
|
+
dependency.each do |additional_key|
|
81
|
+
object[additional_key] = generate(schema.properties[additional_key], hint: hint, position: "#{position}/dependencies/#{key}/#{additional_key}") unless object.has_key?(additional_key)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def generate_by_enum(schema, hint: nil, position:)
|
88
|
+
black_list = (hint ? hint[:not_be_values] : nil)
|
89
|
+
|
90
|
+
if ::JsonSchema::Faker::Configuration.logger
|
91
|
+
::JsonSchema::Faker::Configuration.logger.info "generate by enum at #{position}"
|
92
|
+
::JsonSchema::Faker::Configuration.logger.debug schema.inspect_schema
|
93
|
+
::JsonSchema::Faker::Configuration.logger.debug "black list: #{black_list}" if black_list
|
94
|
+
end
|
95
|
+
|
96
|
+
if black_list
|
97
|
+
(schema.enum - black_list).first
|
98
|
+
else
|
99
|
+
schema.enum.first
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def generate_by_type(schema, hint: nil, position:)
|
104
|
+
if ::JsonSchema::Faker::Configuration.logger
|
105
|
+
::JsonSchema::Faker::Configuration.logger.info "generate by type at #{position}"
|
106
|
+
::JsonSchema::Faker::Configuration.logger.debug schema.inspect_schema
|
107
|
+
end
|
108
|
+
|
109
|
+
# http://json-schema.org/latest/json-schema-core.html#anchor8
|
110
|
+
# TODO: use include? than first
|
111
|
+
case schema.type.first
|
112
|
+
when "array"
|
113
|
+
generate_for_array(schema, hint: hint, position: position)
|
114
|
+
when "boolean"
|
115
|
+
true
|
116
|
+
when "integer", "number"
|
117
|
+
generate_for_number(schema, hint: hint)
|
118
|
+
when "null"
|
119
|
+
nil
|
120
|
+
when "object", nil
|
121
|
+
# here comes object without properties
|
122
|
+
generate_for_object(schema, hint: hint, position: position)
|
123
|
+
when "string"
|
124
|
+
generate_for_string(schema, hint: hint)
|
125
|
+
else
|
126
|
+
raise "unknown type for #{schema.inspect_schema}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def generate_for_array(schema, hint: nil, position:)
|
131
|
+
# http://json-schema.org/latest/json-schema-validation.html#anchor36
|
132
|
+
# additionalItems items maxItems minItems uniqueItems
|
133
|
+
length = schema.min_items || 0
|
134
|
+
|
135
|
+
if schema.items.nil?
|
136
|
+
length.times.map.with_index {|i| i }
|
137
|
+
else
|
138
|
+
if schema.items.is_a?(Array)
|
139
|
+
items = schema.items.map.with_index {|e, i| generate(e, hint: hint, position: "#{position}/items[#{i}]") }
|
140
|
+
|
141
|
+
items + (length - items.size).map.with_index {|i| schema.additional_items === false ? i : generate(schema.additional_items, hint: hint, position: "#{position}/additional_items[#{i}]") }
|
142
|
+
else
|
143
|
+
length.times.map.with_index {|i| generate(schema.items, hint: hint, position: "#{position}/items[#{i}]") }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def generate_for_number(schema, hint: nil)
|
149
|
+
# http://json-schema.org/latest/json-schema-validation.html#anchor13
|
150
|
+
# TODO: use hint[:not_be_values]
|
151
|
+
min = schema.min
|
152
|
+
max = schema.max
|
153
|
+
|
154
|
+
if schema.multiple_of
|
155
|
+
min = (min + schema.multiple_of - min % schema.multiple_of) if min
|
156
|
+
max = (max - max % schema.multiple_of) if max
|
157
|
+
end
|
158
|
+
|
159
|
+
delta = schema.multiple_of ? schema.multiple_of : 1
|
160
|
+
|
161
|
+
# TODO: more sophisticated caluculation
|
162
|
+
min, max = [ (min || (max ? max - delta * 2 : 0)), (max || (min ? min + delta * 2 : 0)) ]
|
163
|
+
|
164
|
+
# to get average of min and max can avoid exclusive*
|
165
|
+
if schema.type.first == "integer"
|
166
|
+
(min / delta + max / delta) / 2 * delta
|
167
|
+
else
|
168
|
+
(min + max) / 2.0
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def generate_for_string(schema, hint: nil)
|
173
|
+
# http://json-schema.org/latest/json-schema-validation.html#anchor25
|
174
|
+
# TODO: use hint[:not_be_values]
|
175
|
+
# TODO: support format
|
176
|
+
if schema.pattern
|
177
|
+
::Pxeger.new(schema.pattern).generate
|
178
|
+
else
|
179
|
+
length = schema.min_length || 0
|
180
|
+
"a" * length
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def compact_and_merge_schema(a, b, a_position:, b_position:)
|
185
|
+
merge_schema!(
|
186
|
+
compact_schema(a, position: a_position),
|
187
|
+
compact_schema(b, position: b_position),
|
188
|
+
a_position: a_position,
|
189
|
+
b_position: b_position
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
def compact_schema(schema, position:)
|
194
|
+
return schema if schema.one_of.empty? && schema.any_of.empty? && schema.all_of.empty?
|
195
|
+
|
196
|
+
if ::JsonSchema::Faker::Configuration.logger
|
197
|
+
::JsonSchema::Faker::Configuration.logger.info "start to compact at #{position}"
|
198
|
+
::JsonSchema::Faker::Configuration.logger.debug schema.inspect_schema
|
199
|
+
end
|
200
|
+
|
201
|
+
merged_schema = ::JsonSchema::Schema.new
|
202
|
+
merged_schema.copy_from(schema)
|
203
|
+
merged_schema.one_of = []
|
204
|
+
merged_schema.any_of = []
|
205
|
+
merged_schema.all_of = []
|
206
|
+
|
207
|
+
unless schema.one_of.empty?
|
208
|
+
::JsonSchema::Faker::Configuration.logger.info "compact one_of" if ::JsonSchema::Faker::Configuration.logger
|
209
|
+
compact_and_merge_schema(merged_schema, schema.one_of.first, a_position: position, b_position: "#{position}/one_of[0]")
|
210
|
+
end
|
211
|
+
|
212
|
+
unless schema.any_of.empty?
|
213
|
+
::JsonSchema::Faker::Configuration.logger.info "compact any_of" if ::JsonSchema::Faker::Configuration.logger
|
214
|
+
compact_and_merge_schema(merged_schema, schema.any_of.first, a_position: position, b_position: "#{position}/any_of[0]")
|
215
|
+
end
|
216
|
+
|
217
|
+
unless schema.all_of.empty?
|
218
|
+
::JsonSchema::Faker::Configuration.logger.info "compact all_of" if ::JsonSchema::Faker::Configuration.logger
|
219
|
+
all_of = ::JsonSchema::Schema.new
|
220
|
+
all_of.copy_from(schema.all_of.first)
|
221
|
+
|
222
|
+
all_of = schema.all_of[1..-1].each.with_index.inject(all_of) do |(a, _), (b, i)|
|
223
|
+
compact_and_merge_schema(a, b, a_position: "#{position}/all_of", b_position: "#{position}/all_of[#{i+1}]")
|
224
|
+
end
|
225
|
+
|
226
|
+
merge_schema!(merged_schema, all_of, a_position: position, b_position: "#{position}/all_of")
|
227
|
+
end
|
228
|
+
|
229
|
+
::JsonSchema::Faker::Configuration.logger.debug "compacted: #{merged_schema.inspect_schema}" if ::JsonSchema::Faker::Configuration.logger
|
230
|
+
|
231
|
+
merged_schema
|
232
|
+
end
|
233
|
+
|
234
|
+
def merge_schema!(a, b, a_position:, b_position:)
|
235
|
+
if ::JsonSchema::Faker::Configuration.logger
|
236
|
+
::JsonSchema::Faker::Configuration.logger.info "start to merge at #{a_position} with #{b_position}"
|
237
|
+
::JsonSchema::Faker::Configuration.logger.debug "a: #{a.inspect_schema}"
|
238
|
+
::JsonSchema::Faker::Configuration.logger.debug "b: #{b.inspect_schema}"
|
239
|
+
end
|
240
|
+
# attr not supported now
|
241
|
+
# not: too difficult (if `not` is not wrapped by all_of wrap it?)
|
242
|
+
# multiple_of TODO: least common multiple
|
243
|
+
# format TODO: just override
|
244
|
+
|
245
|
+
# array properties
|
246
|
+
a.any_of = (a.any_of.empty? ? b.any_of : a.any_of) # XXX: actually impossible
|
247
|
+
a.enum = (a.enum ? (a.enum & b.enum) : b.enum) if b.enum
|
248
|
+
|
249
|
+
%i[ type one_of all_of ].each do |attr|
|
250
|
+
a.__send__("#{attr}=", a.__send__(attr) + b.__send__(attr))
|
251
|
+
end
|
252
|
+
a.required = (a.required ? (a.required + b.required).uniq : b.required) if b.required
|
253
|
+
|
254
|
+
# object properties
|
255
|
+
# XXX: key conflict
|
256
|
+
%i[ properties pattern_properties dependencies ].each do |attr|
|
257
|
+
a.__send__("#{attr}=", a.__send__(attr).merge(b.__send__(attr)))
|
258
|
+
end
|
259
|
+
|
260
|
+
# array of object
|
261
|
+
if a.items && b.items
|
262
|
+
if a.items.is_a?(Array) && b.items.is_a?(Array)
|
263
|
+
# TODO: zip and merge it
|
264
|
+
elsif a.items.is_a?(Array) && b.items.is_a?(::JsonSchema::Schema)
|
265
|
+
a.items = a.items.map.with_index do |e, i|
|
266
|
+
compact_and_merge_schema(e, b.items, a_position: "#{a_position}/items[#{i}]", b_position: "#{b_position}/items")
|
267
|
+
end
|
268
|
+
elsif a.items.is_a?(::JsonSchema::Schema) && a.items.is_a?(Array)
|
269
|
+
a.items = b.items.map.with_index do |e, i|
|
270
|
+
compact_and_merge_schema(a.items, e, a_position: "#{a_position}/items", b_position: "#{b_position}/items[#{i}]")
|
271
|
+
end
|
272
|
+
else
|
273
|
+
compact_and_merge_schema(a.items, b.items, a_position: "#{a_position}/items", b_position: "#{b_position}/items")
|
274
|
+
end
|
275
|
+
else
|
276
|
+
a.items ||= b.items
|
277
|
+
end
|
278
|
+
|
279
|
+
# override to stronger validation
|
280
|
+
%i[ additional_items additional_properties ].each do |attr|
|
281
|
+
a.__send__("#{attr}=", false) unless a.__send__(attr) && b.__send__(attr)
|
282
|
+
end
|
283
|
+
%i[ min_exclusive max_exclusive unique_items ].each do |attr|
|
284
|
+
a.__send__("#{attr}=", a.__send__(attr) & b.__send__(attr))
|
285
|
+
end
|
286
|
+
%i[ min min_length min_properties min_items ].each do |attr|
|
287
|
+
if b.__send__(attr)
|
288
|
+
if a.__send__(attr)
|
289
|
+
a.__send__("#{attr}=", b.__send__(attr)) if b.__send__(attr) < a.__send__(attr)
|
290
|
+
else
|
291
|
+
a.__send__("#{attr}=", b.__send__(attr))
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
%i[ max max_length max_properties max_items ].each do |attr|
|
296
|
+
if b.__send__(attr)
|
297
|
+
if a.__send__(attr)
|
298
|
+
a.__send__("#{attr}=", b.__send__(attr)) if b.__send__(attr) > a.__send__(attr)
|
299
|
+
else
|
300
|
+
a.__send__("#{attr}=", b.__send__(attr))
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
a.pattern = (a.pattern && b.pattern) ? "(?:#{a.pattern})(?=#{b.pattern})" : (a.pattern || b.pattern)
|
305
|
+
|
306
|
+
::JsonSchema::Faker::Configuration.logger.debug "merged: #{a.inspect_schema}" if ::JsonSchema::Faker::Configuration.logger
|
307
|
+
|
308
|
+
a
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_schema-faker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- okitan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json_schema
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- ".gitmodules"
|
120
120
|
- ".rspec"
|
121
121
|
- ".travis.yml"
|
122
|
+
- CHANGELOG.md
|
122
123
|
- CODE_OF_CONDUCT.md
|
123
124
|
- Gemfile
|
124
125
|
- Guardfile
|
@@ -130,6 +131,7 @@ files:
|
|
130
131
|
- bin/setup
|
131
132
|
- json_schema-faker.gemspec
|
132
133
|
- lib/json_schema/faker.rb
|
134
|
+
- lib/json_schema/faker/strategy/simple.rb
|
133
135
|
homepage: https://github.com/okitan/json_schema-faker
|
134
136
|
licenses:
|
135
137
|
- MIT
|