json_schemer 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/lib/json_schemer.rb +13 -1
- data/lib/json_schemer/format.rb +0 -6
- data/lib/json_schemer/schema/base.rb +81 -55
- data/lib/json_schemer/schema/draft4.rb +2 -2
- data/lib/json_schemer/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99e547dd87197c33f01403e652c5ddecdb1dc39df0e63071a588135a94100960
|
4
|
+
data.tar.gz: d2b6d281eaa5d6d228ef5a90ea1d8ddbd22574f72d638c83d3fe48b1fd50825c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a506748ca559c13ae0c05204011be6bd5650c8982ef2fdd4e4874bc094664201a7d5856f1cceea5b5773956c74cb4d7e1a68c9b1c8165e3c1ce40d48fcef6ed
|
7
|
+
data.tar.gz: ae1eaa5e38b44e88244ab51782184f397050ce07d0ace89ef450777d4be4a7c1c2003b7d8e66df7c9f1a373b2ef1b1a27c0b8c5d26d03cbabe01645f3ecf6894
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
json_schemer (0.
|
4
|
+
json_schemer (0.2.0)
|
5
5
|
ecma-re-validator (~> 0.2.0)
|
6
6
|
hana (~> 1.3.3)
|
7
7
|
regexp_parser (~> 1.2.0)
|
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
specs:
|
13
13
|
ecma-re-validator (0.2.0)
|
14
14
|
regexp_parser (~> 1.2)
|
15
|
-
hana (1.3.
|
15
|
+
hana (1.3.5)
|
16
16
|
minitest (5.11.1)
|
17
17
|
rake (10.5.0)
|
18
18
|
regexp_parser (1.2.0)
|
data/lib/json_schemer.rb
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'base64'
|
4
|
+
require 'json'
|
5
|
+
require 'net/http'
|
6
|
+
require 'pathname'
|
7
|
+
require 'time'
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
require 'ecma-re-validator'
|
11
|
+
require 'hana'
|
12
|
+
require 'ipaddr'
|
13
|
+
require 'uri_template'
|
14
|
+
|
3
15
|
require 'json_schemer/version'
|
4
16
|
require 'json_schemer/format'
|
5
17
|
require 'json_schemer/cached_ref_resolver'
|
@@ -7,11 +19,11 @@ require 'json_schemer/schema/base'
|
|
7
19
|
require 'json_schemer/schema/draft4'
|
8
20
|
require 'json_schemer/schema/draft6'
|
9
21
|
require 'json_schemer/schema/draft7'
|
10
|
-
require 'pathname'
|
11
22
|
|
12
23
|
module JSONSchemer
|
13
24
|
class UnsupportedMetaSchema < StandardError; end
|
14
25
|
class UnknownRef < StandardError; end
|
26
|
+
class InvalidRefResolution < StandardError; end
|
15
27
|
class InvalidFileURI < StandardError; end
|
16
28
|
class InvalidSymbolKey < StandardError; end
|
17
29
|
|
data/lib/json_schemer/format.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64'
|
4
|
-
require 'hana'
|
5
|
-
require 'json'
|
6
|
-
require 'net/http'
|
7
|
-
require 'time'
|
8
|
-
require 'uri'
|
9
|
-
|
10
3
|
module JSONSchemer
|
11
4
|
module Schema
|
12
5
|
class Base
|
@@ -25,8 +18,8 @@ module JSONSchemer
|
|
25
18
|
end
|
26
19
|
|
27
20
|
ID_KEYWORD = '$id'
|
28
|
-
DEFAULT_REF_RESOLVER = proc { |uri| raise UnknownRef, uri.to_s }
|
29
|
-
NET_HTTP_REF_RESOLVER = proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
|
21
|
+
DEFAULT_REF_RESOLVER = proc { |uri| raise UnknownRef, uri.to_s }
|
22
|
+
NET_HTTP_REF_RESOLVER = proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
|
30
23
|
BOOLEANS = Set[true, false].freeze
|
31
24
|
|
32
25
|
RUBY_REGEX_ANCHORS_TO_ECMA_262 = {
|
@@ -43,7 +36,7 @@ module JSONSchemer
|
|
43
36
|
keywords: nil,
|
44
37
|
ref_resolver: DEFAULT_REF_RESOLVER
|
45
38
|
)
|
46
|
-
raise InvalidSymbolKey, 'schemas must use string keys' if schema.is_a?(Hash) && schema.first.first.is_a?(
|
39
|
+
raise InvalidSymbolKey, 'schemas must use string keys' if schema.is_a?(Hash) && !schema.first.first.is_a?(String)
|
47
40
|
@root = schema
|
48
41
|
@format = format
|
49
42
|
@formats = formats
|
@@ -65,18 +58,17 @@ module JSONSchemer
|
|
65
58
|
validate_instance(instance).none?
|
66
59
|
end
|
67
60
|
|
68
|
-
def validate_instance(instance)
|
61
|
+
def validate_instance(instance, &block)
|
69
62
|
return enum_for(:validate_instance, instance) unless block_given?
|
70
63
|
|
71
64
|
schema = instance.schema
|
72
65
|
|
73
|
-
return if schema == true
|
74
66
|
if schema == false
|
75
67
|
yield error(instance, 'schema')
|
76
68
|
return
|
77
69
|
end
|
78
70
|
|
79
|
-
return if schema.empty?
|
71
|
+
return if schema == true || schema.empty?
|
80
72
|
|
81
73
|
type = schema['type']
|
82
74
|
enum = schema['enum']
|
@@ -94,12 +86,12 @@ module JSONSchemer
|
|
94
86
|
instance.parent_uri = join_uri(instance.parent_uri, id)
|
95
87
|
|
96
88
|
if ref
|
97
|
-
validate_ref(instance, ref, &
|
89
|
+
validate_ref(instance, ref, &block)
|
98
90
|
return
|
99
91
|
end
|
100
92
|
|
101
93
|
if format? && custom_format?(format)
|
102
|
-
validate_custom_format(instance, formats.fetch(format), &
|
94
|
+
validate_custom_format(instance, formats.fetch(format), &block)
|
103
95
|
end
|
104
96
|
|
105
97
|
if keywords
|
@@ -107,7 +99,7 @@ module JSONSchemer
|
|
107
99
|
if schema.key?(keyword)
|
108
100
|
result = callable.call(data, schema, instance.pointer)
|
109
101
|
if result.is_a?(Array)
|
110
|
-
result.each
|
102
|
+
result.each(&block)
|
111
103
|
elsif !result
|
112
104
|
yield error(instance, keyword)
|
113
105
|
end
|
@@ -120,25 +112,50 @@ module JSONSchemer
|
|
120
112
|
yield error(instance, 'enum') if enum && !enum.include?(data)
|
121
113
|
yield error(instance, 'const') if schema.key?('const') && schema['const'] != data
|
122
114
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
115
|
+
if all_of
|
116
|
+
all_of.each_with_index do |subschema, index|
|
117
|
+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/allOf/#{index}"), &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
if any_of
|
122
|
+
subschemas = any_of.lazy.with_index.map do |subschema, index|
|
123
|
+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/anyOf/#{index}"))
|
124
|
+
end
|
125
|
+
subschemas.each { |subschema| subschema.each(&block) } unless subschemas.any?(&:none?)
|
126
|
+
end
|
127
|
+
|
128
|
+
if one_of
|
129
|
+
subschemas = one_of.map.with_index do |subschema, index|
|
130
|
+
validate_instance(instance.merge(schema: subschema, schema_pointer: "#{instance.schema_pointer}/oneOf/#{index}"))
|
131
|
+
end
|
132
|
+
valid_subschema_count = subschemas.count(&:none?)
|
133
|
+
if valid_subschema_count > 1
|
134
|
+
yield error(instance, 'oneOf')
|
135
|
+
elsif valid_subschema_count == 0
|
136
|
+
subschemas.each { |subschema| subschema.each(&block) }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
unless not_schema.nil?
|
141
|
+
subinstance = instance.merge(schema: not_schema, schema_pointer: "#{instance.schema_pointer}/not")
|
142
|
+
yield error(subinstance, 'not') if valid_instance?(subinstance)
|
143
|
+
end
|
127
144
|
|
128
145
|
if if_schema && valid_instance?(instance.merge(schema: if_schema))
|
129
|
-
|
146
|
+
validate_instance(instance.merge(schema: then_schema, schema_pointer: "#{instance.schema_pointer}/then"), &block) unless then_schema.nil?
|
130
147
|
elsif if_schema
|
131
|
-
|
148
|
+
validate_instance(instance.merge(schema: else_schema, schema_pointer: "#{instance.schema_pointer}/else"), &block) unless else_schema.nil?
|
132
149
|
end
|
133
150
|
|
134
151
|
case type
|
135
152
|
when nil
|
136
|
-
validate_class(instance, &
|
153
|
+
validate_class(instance, &block)
|
137
154
|
when String
|
138
|
-
validate_type(instance, type, &
|
155
|
+
validate_type(instance, type, &block)
|
139
156
|
when Array
|
140
157
|
if valid_type = type.find { |subtype| valid_instance?(instance.merge(schema: { 'type' => subtype })) }
|
141
|
-
validate_type(instance, valid_type, &
|
158
|
+
validate_type(instance, valid_type, &block)
|
142
159
|
else
|
143
160
|
yield error(instance, 'type')
|
144
161
|
end
|
@@ -179,8 +196,8 @@ module JSONSchemer
|
|
179
196
|
)
|
180
197
|
end
|
181
198
|
|
182
|
-
def error(instance, type)
|
183
|
-
{
|
199
|
+
def error(instance, type, details = nil)
|
200
|
+
error = {
|
184
201
|
'data' => instance.data,
|
185
202
|
'data_pointer' => instance.data_pointer,
|
186
203
|
'schema' => instance.schema,
|
@@ -188,43 +205,45 @@ module JSONSchemer
|
|
188
205
|
'root_schema' => root,
|
189
206
|
'type' => type,
|
190
207
|
}
|
208
|
+
error['details'] = details if details
|
209
|
+
error
|
191
210
|
end
|
192
211
|
|
193
|
-
def validate_class(instance)
|
212
|
+
def validate_class(instance, &block)
|
194
213
|
case instance.data
|
195
214
|
when Integer
|
196
|
-
validate_integer(instance, &
|
215
|
+
validate_integer(instance, &block)
|
197
216
|
when Numeric
|
198
|
-
validate_number(instance, &
|
217
|
+
validate_number(instance, &block)
|
199
218
|
when String
|
200
|
-
validate_string(instance, &
|
219
|
+
validate_string(instance, &block)
|
201
220
|
when Array
|
202
|
-
validate_array(instance, &
|
221
|
+
validate_array(instance, &block)
|
203
222
|
when Hash
|
204
|
-
validate_object(instance, &
|
223
|
+
validate_object(instance, &block)
|
205
224
|
end
|
206
225
|
end
|
207
226
|
|
208
|
-
def validate_type(instance, type)
|
227
|
+
def validate_type(instance, type, &block)
|
209
228
|
case type
|
210
229
|
when 'null'
|
211
230
|
yield error(instance, 'null') unless instance.data.nil?
|
212
231
|
when 'boolean'
|
213
232
|
yield error(instance, 'boolean') unless BOOLEANS.include?(instance.data)
|
214
233
|
when 'number'
|
215
|
-
validate_number(instance, &
|
234
|
+
validate_number(instance, &block)
|
216
235
|
when 'integer'
|
217
|
-
validate_integer(instance, &
|
236
|
+
validate_integer(instance, &block)
|
218
237
|
when 'string'
|
219
|
-
validate_string(instance, &
|
238
|
+
validate_string(instance, &block)
|
220
239
|
when 'array'
|
221
|
-
validate_array(instance, &
|
240
|
+
validate_array(instance, &block)
|
222
241
|
when 'object'
|
223
|
-
validate_object(instance, &
|
242
|
+
validate_object(instance, &block)
|
224
243
|
end
|
225
244
|
end
|
226
245
|
|
227
|
-
def validate_ref(instance, ref)
|
246
|
+
def validate_ref(instance, ref, &block)
|
228
247
|
ref_uri = join_uri(instance.parent_uri, ref)
|
229
248
|
|
230
249
|
if valid_json_pointer?(ref_uri.fragment)
|
@@ -235,16 +254,16 @@ module JSONSchemer
|
|
235
254
|
schema_pointer: ref_uri.fragment,
|
236
255
|
parent_uri: pointer_uri(root, ref_pointer)
|
237
256
|
)
|
238
|
-
validate_instance(subinstance, &
|
257
|
+
validate_instance(subinstance, &block)
|
239
258
|
else
|
240
|
-
ref_root =
|
259
|
+
ref_root = resolve_ref(ref_uri)
|
241
260
|
ref_object = child(ref_root)
|
242
261
|
subinstance = instance.merge(
|
243
262
|
schema: ref_pointer.eval(ref_root),
|
244
263
|
schema_pointer: ref_uri.fragment,
|
245
264
|
parent_uri: pointer_uri(ref_root, ref_pointer)
|
246
265
|
)
|
247
|
-
ref_object.validate_instance(subinstance, &
|
266
|
+
ref_object.validate_instance(subinstance, &block)
|
248
267
|
end
|
249
268
|
elsif id = ids[ref_uri.to_s]
|
250
269
|
subinstance = instance.merge(
|
@@ -252,9 +271,9 @@ module JSONSchemer
|
|
252
271
|
schema_pointer: id.fetch(:pointer),
|
253
272
|
parent_uri: ref_uri
|
254
273
|
)
|
255
|
-
validate_instance(subinstance, &
|
274
|
+
validate_instance(subinstance, &block)
|
256
275
|
else
|
257
|
-
ref_root =
|
276
|
+
ref_root = resolve_ref(ref_uri)
|
258
277
|
ref_object = child(ref_root)
|
259
278
|
id = ref_object.ids[ref_uri.to_s] || { schema: ref_root, pointer: '' }
|
260
279
|
subinstance = instance.merge(
|
@@ -262,7 +281,7 @@ module JSONSchemer
|
|
262
281
|
schema_pointer: id.fetch(:pointer),
|
263
282
|
parent_uri: ref_uri
|
264
283
|
)
|
265
|
-
ref_object.validate_instance(subinstance, &
|
284
|
+
ref_object.validate_instance(subinstance, &block)
|
266
285
|
end
|
267
286
|
end
|
268
287
|
|
@@ -278,7 +297,7 @@ module JSONSchemer
|
|
278
297
|
yield error(instance, 'exclusiveMinimum') if instance.data <= exclusive_minimum
|
279
298
|
end
|
280
299
|
|
281
|
-
def validate_numeric(instance)
|
300
|
+
def validate_numeric(instance, &block)
|
282
301
|
schema = instance.schema
|
283
302
|
data = instance.data
|
284
303
|
|
@@ -291,8 +310,8 @@ module JSONSchemer
|
|
291
310
|
yield error(instance, 'maximum') if maximum && data > maximum
|
292
311
|
yield error(instance, 'minimum') if minimum && data < minimum
|
293
312
|
|
294
|
-
validate_exclusive_maximum(instance, exclusive_maximum, maximum, &
|
295
|
-
validate_exclusive_minimum(instance, exclusive_minimum, minimum, &
|
313
|
+
validate_exclusive_maximum(instance, exclusive_maximum, maximum, &block) if exclusive_maximum
|
314
|
+
validate_exclusive_minimum(instance, exclusive_minimum, minimum, &block) if exclusive_minimum
|
296
315
|
|
297
316
|
if multiple_of
|
298
317
|
quotient = data / multiple_of.to_f
|
@@ -300,16 +319,16 @@ module JSONSchemer
|
|
300
319
|
end
|
301
320
|
end
|
302
321
|
|
303
|
-
def validate_number(instance)
|
322
|
+
def validate_number(instance, &block)
|
304
323
|
unless instance.data.is_a?(Numeric)
|
305
324
|
yield error(instance, 'number')
|
306
325
|
return
|
307
326
|
end
|
308
327
|
|
309
|
-
validate_numeric(instance, &
|
328
|
+
validate_numeric(instance, &block)
|
310
329
|
end
|
311
330
|
|
312
|
-
def validate_integer(instance)
|
331
|
+
def validate_integer(instance, &block)
|
313
332
|
data = instance.data
|
314
333
|
|
315
334
|
if !data.is_a?(Numeric) || (!data.is_a?(Integer) && data.floor != data)
|
@@ -317,10 +336,10 @@ module JSONSchemer
|
|
317
336
|
return
|
318
337
|
end
|
319
338
|
|
320
|
-
validate_numeric(instance, &
|
339
|
+
validate_numeric(instance, &block)
|
321
340
|
end
|
322
341
|
|
323
|
-
def validate_string(instance)
|
342
|
+
def validate_string(instance, &block)
|
324
343
|
data = instance.data
|
325
344
|
|
326
345
|
unless data.is_a?(String)
|
@@ -453,7 +472,10 @@ module JSONSchemer
|
|
453
472
|
|
454
473
|
yield error(instance, 'maxProperties') if max_properties && data.size > max_properties
|
455
474
|
yield error(instance, 'minProperties') if min_properties && data.size < min_properties
|
456
|
-
|
475
|
+
if required
|
476
|
+
missing_keys = required - data.keys
|
477
|
+
yield error(instance, 'required', 'missing_keys' => missing_keys) if missing_keys.any?
|
478
|
+
end
|
457
479
|
|
458
480
|
regex_pattern_properties = nil
|
459
481
|
data.each do |key, value|
|
@@ -570,6 +592,10 @@ module JSONSchemer
|
|
570
592
|
end
|
571
593
|
ids
|
572
594
|
end
|
595
|
+
|
596
|
+
def resolve_ref(uri)
|
597
|
+
ref_resolver.call(uri) || raise(InvalidRefResolution, uri.to_s)
|
598
|
+
end
|
573
599
|
end
|
574
600
|
end
|
575
601
|
end
|
@@ -32,13 +32,13 @@ module JSONSchemer
|
|
32
32
|
yield error(instance, 'exclusiveMinimum') if exclusive_minimum && instance.data <= minimum
|
33
33
|
end
|
34
34
|
|
35
|
-
def validate_integer(instance)
|
35
|
+
def validate_integer(instance, &block)
|
36
36
|
if !instance.data.is_a?(Integer)
|
37
37
|
yield error(instance, 'integer')
|
38
38
|
return
|
39
39
|
end
|
40
40
|
|
41
|
-
validate_numeric(instance, &
|
41
|
+
validate_numeric(instance, &block)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/json_schemer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_schemer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Harsha
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,7 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '0'
|
155
155
|
requirements: []
|
156
|
-
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.7.6
|
157
158
|
signing_key:
|
158
159
|
specification_version: 4
|
159
160
|
summary: JSON Schema validator. Supports drafts 4, 6, and 7.
|