json-schema 2.8.0 → 5.1.1
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 +5 -5
- data/README.md +82 -11
- data/lib/json-schema/attribute.rb +13 -14
- data/lib/json-schema/attributes/additionalitems.rb +1 -0
- data/lib/json-schema/attributes/additionalproperties.rb +3 -6
- data/lib/json-schema/attributes/allof.rb +6 -4
- data/lib/json-schema/attributes/anyof.rb +2 -2
- data/lib/json-schema/attributes/const.rb +15 -0
- data/lib/json-schema/attributes/dependencies.rb +1 -6
- data/lib/json-schema/attributes/dependencies_v4.rb +11 -0
- data/lib/json-schema/attributes/disallow.rb +2 -1
- data/lib/json-schema/attributes/divisibleby.rb +1 -1
- data/lib/json-schema/attributes/enum.rb +2 -2
- data/lib/json-schema/attributes/extends.rb +7 -7
- data/lib/json-schema/attributes/format.rb +2 -1
- data/lib/json-schema/attributes/formats/custom.rb +1 -1
- data/lib/json-schema/attributes/formats/date.rb +2 -1
- data/lib/json-schema/attributes/formats/date_time.rb +3 -2
- data/lib/json-schema/attributes/formats/date_time_v4.rb +2 -1
- data/lib/json-schema/attributes/formats/ip.rb +1 -1
- data/lib/json-schema/attributes/formats/time.rb +1 -1
- data/lib/json-schema/attributes/formats/uri.rb +2 -1
- data/lib/json-schema/attributes/items.rb +1 -0
- data/lib/json-schema/attributes/limit.rb +0 -127
- data/lib/json-schema/attributes/limits/items.rb +15 -0
- data/lib/json-schema/attributes/limits/length.rb +15 -0
- data/lib/json-schema/attributes/limits/max_items.rb +15 -0
- data/lib/json-schema/attributes/limits/max_length.rb +15 -0
- data/lib/json-schema/attributes/limits/max_properties.rb +15 -0
- data/lib/json-schema/attributes/limits/maximum.rb +15 -0
- data/lib/json-schema/attributes/limits/maximum_inclusive.rb +11 -0
- data/lib/json-schema/attributes/limits/min_items.rb +15 -0
- data/lib/json-schema/attributes/limits/min_length.rb +15 -0
- data/lib/json-schema/attributes/limits/min_properties.rb +15 -0
- data/lib/json-schema/attributes/limits/minimum.rb +15 -0
- data/lib/json-schema/attributes/limits/minimum_inclusive.rb +11 -0
- data/lib/json-schema/attributes/limits/numeric.rb +16 -0
- data/lib/json-schema/attributes/limits/properties.rb +15 -0
- data/lib/json-schema/attributes/maxdecimal.rb +1 -1
- data/lib/json-schema/attributes/not.rb +2 -2
- data/lib/json-schema/attributes/oneof.rb +2 -4
- data/lib/json-schema/attributes/patternproperties.rb +2 -1
- data/lib/json-schema/attributes/properties.rb +9 -17
- data/lib/json-schema/attributes/properties_v4.rb +13 -0
- data/lib/json-schema/attributes/propertynames.rb +23 -0
- data/lib/json-schema/attributes/ref.rb +8 -8
- data/lib/json-schema/attributes/required.rb +4 -3
- data/lib/json-schema/attributes/type.rb +3 -2
- data/lib/json-schema/attributes/type_v4.rb +1 -1
- data/lib/json-schema/errors/validation_error.rb +5 -6
- data/lib/json-schema/schema/reader.rb +3 -1
- data/lib/json-schema/schema/validator.rb +3 -3
- data/lib/json-schema/schema.rb +3 -4
- data/lib/json-schema/util/array_set.rb +1 -1
- data/lib/json-schema/util/uri.rb +98 -75
- data/lib/json-schema/util/uuid.rb +203 -226
- data/lib/json-schema/validator.rb +122 -115
- data/lib/json-schema/validators/draft1.rb +21 -23
- data/lib/json-schema/validators/draft2.rb +22 -24
- data/lib/json-schema/validators/draft3.rb +26 -28
- data/lib/json-schema/validators/draft4.rb +34 -36
- data/lib/json-schema/validators/draft6.rb +36 -36
- data/lib/json-schema/validators/hyper-draft1.rb +2 -3
- data/lib/json-schema/validators/hyper-draft2.rb +2 -3
- data/lib/json-schema/validators/hyper-draft3.rb +2 -3
- data/lib/json-schema/validators/hyper-draft4.rb +2 -3
- data/lib/json-schema/validators/hyper-draft6.rb +2 -3
- data/lib/json-schema.rb +2 -3
- data/resources/draft-06.json +41 -41
- metadata +67 -31
@@ -4,6 +4,8 @@ require 'bigdecimal'
|
|
4
4
|
require 'digest/sha1'
|
5
5
|
require 'date'
|
6
6
|
require 'thread'
|
7
|
+
require 'timeout'
|
8
|
+
require 'stringio'
|
7
9
|
require 'yaml'
|
8
10
|
|
9
11
|
require 'json-schema/schema/reader'
|
@@ -14,21 +16,22 @@ require 'json-schema/errors/json_parse_error'
|
|
14
16
|
require 'json-schema/util/uri'
|
15
17
|
|
16
18
|
module JSON
|
17
|
-
|
18
19
|
class Validator
|
19
|
-
|
20
20
|
@@schemas = {}
|
21
21
|
@@cache_schemas = true
|
22
22
|
@@default_opts = {
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
23
|
+
list: false,
|
24
|
+
version: nil,
|
25
|
+
validate_schema: false,
|
26
|
+
record_errors: false,
|
27
|
+
errors_as_objects: false,
|
28
|
+
insert_defaults: false,
|
29
|
+
clear_cache: false,
|
30
|
+
strict: false,
|
31
|
+
allPropertiesRequired: false,
|
32
|
+
noAdditionalProperties: false,
|
33
|
+
parse_data: true,
|
34
|
+
parse_integer: true,
|
32
35
|
}
|
33
36
|
@@validators = {}
|
34
37
|
@@default_validator = nil
|
@@ -37,32 +40,32 @@ module JSON
|
|
37
40
|
@@serializer = nil
|
38
41
|
@@mutex = Mutex.new
|
39
42
|
|
40
|
-
def initialize(schema_data,
|
43
|
+
def initialize(schema_data, opts = {})
|
41
44
|
@options = @@default_opts.clone.merge(opts)
|
42
45
|
@errors = []
|
43
46
|
|
44
|
-
|
45
|
-
@options[:version] = validator
|
47
|
+
configured_validator = self.class.validator_for_name(@options[:version])
|
46
48
|
@options[:schema_reader] ||= self.class.schema_reader
|
47
49
|
|
48
|
-
@validation_options = @options[:record_errors] ? {:
|
50
|
+
@validation_options = @options[:record_errors] ? { record_errors: true } : {}
|
49
51
|
@validation_options[:insert_defaults] = true if @options[:insert_defaults]
|
50
|
-
|
52
|
+
if @options[:strict] == true
|
53
|
+
@validation_options[:allPropertiesRequired] = true
|
54
|
+
@validation_options[:noAdditionalProperties] = true
|
55
|
+
else
|
56
|
+
@validation_options[:allPropertiesRequired] = true if @options[:allPropertiesRequired]
|
57
|
+
@validation_options[:noAdditionalProperties] = true if @options[:noAdditionalProperties]
|
58
|
+
end
|
51
59
|
@validation_options[:clear_cache] = true if !@@cache_schemas || @options[:clear_cache]
|
52
60
|
|
53
|
-
@@mutex.synchronize { @base_schema = initialize_schema(schema_data) }
|
54
|
-
@original_data = data
|
55
|
-
@data = initialize_data(data)
|
61
|
+
@@mutex.synchronize { @base_schema = initialize_schema(schema_data, configured_validator) }
|
56
62
|
@@mutex.synchronize { build_schemas(@base_schema) }
|
57
63
|
|
58
64
|
# validate the schema, if requested
|
59
65
|
if @options[:validate_schema]
|
60
|
-
if @base_schema.schema["$schema"]
|
61
|
-
base_validator = self.class.validator_for_name(@base_schema.schema["$schema"])
|
62
|
-
end
|
63
|
-
metaschema = base_validator ? base_validator.metaschema : validator.metaschema
|
64
66
|
# Don't clear the cache during metaschema validation!
|
65
|
-
self.class.
|
67
|
+
meta_validator = self.class.new(@base_schema.validator.metaschema, { clear_cache: false })
|
68
|
+
meta_validator.validate(@base_schema.schema)
|
66
69
|
end
|
67
70
|
|
68
71
|
# If the :fragment option is set, try and validate against the fragment
|
@@ -73,60 +76,61 @@ module JSON
|
|
73
76
|
|
74
77
|
def schema_from_fragment(base_schema, fragment)
|
75
78
|
schema_uri = base_schema.uri
|
76
|
-
fragments = fragment.split(
|
79
|
+
fragments = fragment.split('/').map { |f| f.gsub('~0', '~').gsub('~1', '/') }
|
77
80
|
|
78
81
|
# ensure the first element was a hash, per the fragment spec
|
79
|
-
if fragments.shift !=
|
80
|
-
raise JSON::Schema::SchemaError
|
82
|
+
if fragments.shift != '#'
|
83
|
+
raise JSON::Schema::SchemaError, 'Invalid fragment syntax in :fragment option'
|
81
84
|
end
|
82
85
|
|
86
|
+
schema_fragment = base_schema.schema
|
83
87
|
fragments.each do |f|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
elsif base_schema.is_a?(Hash)
|
90
|
-
if !base_schema.has_key?(f)
|
91
|
-
raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option")
|
92
|
-
end
|
93
|
-
base_schema = JSON::Schema.new(base_schema[f],schema_uri,@options[:version])
|
94
|
-
elsif base_schema.is_a?(Array)
|
95
|
-
if base_schema[f.to_i].nil?
|
96
|
-
raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option")
|
97
|
-
end
|
98
|
-
base_schema = JSON::Schema.new(base_schema[f.to_i],schema_uri,@options[:version])
|
99
|
-
else
|
100
|
-
raise JSON::Schema::SchemaError.new("Invalid schema encountered when resolving :fragment option")
|
88
|
+
case schema_fragment
|
89
|
+
when Hash
|
90
|
+
schema_fragment = schema_fragment[f]
|
91
|
+
when Array
|
92
|
+
schema_fragment = schema_fragment[f.to_i]
|
101
93
|
end
|
102
94
|
end
|
103
95
|
|
96
|
+
unless schema_fragment.is_a?(Hash)
|
97
|
+
raise JSON::Schema::SchemaError, 'Invalid fragment resolution for :fragment option'
|
98
|
+
end
|
99
|
+
|
100
|
+
schema = JSON::Schema.new(schema_fragment, schema_uri, base_schema.validator)
|
101
|
+
|
104
102
|
if @options[:list]
|
105
|
-
|
103
|
+
schema.to_array_schema
|
104
|
+
elsif schema.is_a?(Hash)
|
105
|
+
JSON::Schema.new(schema, schema_uri, @options[:version])
|
106
106
|
else
|
107
|
-
|
107
|
+
schema
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
111
|
# Run a simple true/false validation of data against a schema
|
112
|
-
def validate
|
113
|
-
|
112
|
+
def validate(data)
|
113
|
+
original_data = data
|
114
|
+
data = initialize_data(data)
|
115
|
+
@base_schema.validate(data, [], self, @validation_options)
|
114
116
|
|
115
117
|
if @options[:record_errors]
|
116
118
|
if @options[:errors_as_objects]
|
117
|
-
@errors.map{|e| e.to_hash}
|
119
|
+
@errors.map { |e| e.to_hash }
|
118
120
|
else
|
119
|
-
@errors.map{|e| e.to_string}
|
121
|
+
@errors.map { |e| e.to_string }
|
120
122
|
end
|
121
123
|
else
|
122
124
|
true
|
123
125
|
end
|
124
126
|
ensure
|
127
|
+
@errors = []
|
128
|
+
|
125
129
|
if @validation_options[:clear_cache] == true
|
126
130
|
self.class.clear_cache
|
127
131
|
end
|
128
132
|
if @validation_options[:insert_defaults]
|
129
|
-
self.class.merge_missing_values(
|
133
|
+
self.class.merge_missing_values(data, original_data)
|
130
134
|
end
|
131
135
|
end
|
132
136
|
|
@@ -147,13 +151,13 @@ module JSON
|
|
147
151
|
schema = parent_schema.schema
|
148
152
|
|
149
153
|
# Build ref schemas if they exist
|
150
|
-
if schema[
|
151
|
-
load_ref_schema(parent_schema, schema[
|
154
|
+
if schema['$ref']
|
155
|
+
load_ref_schema(parent_schema, schema['$ref'])
|
152
156
|
end
|
153
157
|
|
154
|
-
case schema[
|
158
|
+
case schema['extends']
|
155
159
|
when String
|
156
|
-
load_ref_schema(parent_schema, schema[
|
160
|
+
load_ref_schema(parent_schema, schema['extends'])
|
157
161
|
when Array
|
158
162
|
schema['extends'].each do |type|
|
159
163
|
handle_schema(parent_schema, type)
|
@@ -161,7 +165,7 @@ module JSON
|
|
161
165
|
end
|
162
166
|
|
163
167
|
# Check for schemas in union types
|
164
|
-
[
|
168
|
+
%w[type disallow].each do |key|
|
165
169
|
if schema[key].is_a?(Array)
|
166
170
|
schema[key].each do |type|
|
167
171
|
if type.is_a?(Hash)
|
@@ -175,7 +179,8 @@ module JSON
|
|
175
179
|
# are themselves schemas.
|
176
180
|
%w[definitions properties patternProperties].each do |key|
|
177
181
|
next unless value = schema[key]
|
178
|
-
|
182
|
+
|
183
|
+
value.each do |_k, inner_schema|
|
179
184
|
handle_schema(parent_schema, inner_schema)
|
180
185
|
end
|
181
186
|
end
|
@@ -183,20 +188,22 @@ module JSON
|
|
183
188
|
# Schema properties whose values are themselves schemas.
|
184
189
|
%w[additionalProperties additionalItems dependencies extends].each do |key|
|
185
190
|
next unless schema[key].is_a?(Hash)
|
191
|
+
|
186
192
|
handle_schema(parent_schema, schema[key])
|
187
193
|
end
|
188
194
|
|
189
195
|
# Schema properties whose values may be an array of schemas.
|
190
196
|
%w[allOf anyOf oneOf not].each do |key|
|
191
197
|
next unless value = schema[key]
|
198
|
+
|
192
199
|
Array(value).each do |inner_schema|
|
193
200
|
handle_schema(parent_schema, inner_schema)
|
194
201
|
end
|
195
202
|
end
|
196
203
|
|
197
204
|
# Items are always schemas
|
198
|
-
if schema[
|
199
|
-
items = schema[
|
205
|
+
if schema['items']
|
206
|
+
items = schema['items'].clone
|
200
207
|
items = [items] unless items.is_a?(Array)
|
201
208
|
|
202
209
|
items.each do |item|
|
@@ -205,10 +212,9 @@ module JSON
|
|
205
212
|
end
|
206
213
|
|
207
214
|
# Convert enum to a ArraySet
|
208
|
-
if schema[
|
209
|
-
schema[
|
215
|
+
if schema['enum'].is_a?(Array)
|
216
|
+
schema['enum'] = ArraySet.new(schema['enum'])
|
210
217
|
end
|
211
|
-
|
212
218
|
end
|
213
219
|
|
214
220
|
# Either load a reference schema or create a new schema
|
@@ -231,58 +237,57 @@ module JSON
|
|
231
237
|
@errors
|
232
238
|
end
|
233
239
|
|
234
|
-
|
235
240
|
class << self
|
236
|
-
def validate(schema, data,opts={})
|
241
|
+
def validate(schema, data, opts = {})
|
237
242
|
begin
|
238
243
|
validate!(schema, data, opts)
|
239
244
|
rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
|
240
|
-
|
245
|
+
false
|
241
246
|
end
|
242
247
|
end
|
243
248
|
|
244
|
-
def validate_json(schema, data, opts={})
|
245
|
-
validate(schema, data, opts.merge(:
|
249
|
+
def validate_json(schema, data, opts = {})
|
250
|
+
validate(schema, data, opts.merge(json: true))
|
246
251
|
end
|
247
252
|
|
248
|
-
def validate_uri(schema, data, opts={})
|
249
|
-
validate(schema, data, opts.merge(:
|
253
|
+
def validate_uri(schema, data, opts = {})
|
254
|
+
validate(schema, data, opts.merge(uri: true))
|
250
255
|
end
|
251
256
|
|
252
|
-
def validate!(schema, data,opts={})
|
253
|
-
validator = new(schema,
|
254
|
-
validator.validate
|
257
|
+
def validate!(schema, data, opts = {})
|
258
|
+
validator = new(schema, opts)
|
259
|
+
validator.validate(data)
|
255
260
|
end
|
256
261
|
|
257
|
-
def validate2(schema, data, opts={})
|
258
|
-
warn
|
262
|
+
def validate2(schema, data, opts = {})
|
263
|
+
warn '[DEPRECATION NOTICE] JSON::Validator#validate2 has been replaced by JSON::Validator#validate! and will be removed in version >= 3. Please use the #validate! method instead.'
|
259
264
|
validate!(schema, data, opts)
|
260
265
|
end
|
261
266
|
|
262
|
-
def validate_json!(schema, data, opts={})
|
263
|
-
validate!(schema, data, opts.merge(:
|
267
|
+
def validate_json!(schema, data, opts = {})
|
268
|
+
validate!(schema, data, opts.merge(json: true))
|
264
269
|
end
|
265
270
|
|
266
|
-
def validate_uri!(schema, data, opts={})
|
267
|
-
validate!(schema, data, opts.merge(:
|
271
|
+
def validate_uri!(schema, data, opts = {})
|
272
|
+
validate!(schema, data, opts.merge(uri: true))
|
268
273
|
end
|
269
274
|
|
270
|
-
def fully_validate(schema, data, opts={})
|
271
|
-
validate!(schema, data, opts.merge(:
|
275
|
+
def fully_validate(schema, data, opts = {})
|
276
|
+
validate!(schema, data, opts.merge(record_errors: true))
|
272
277
|
end
|
273
278
|
|
274
|
-
def fully_validate_schema(schema, opts={})
|
279
|
+
def fully_validate_schema(schema, opts = {})
|
275
280
|
data = schema
|
276
281
|
schema = validator_for_name(opts[:version]).metaschema
|
277
282
|
fully_validate(schema, data, opts)
|
278
283
|
end
|
279
284
|
|
280
|
-
def fully_validate_json(schema, data, opts={})
|
281
|
-
fully_validate(schema, data, opts.merge(:
|
285
|
+
def fully_validate_json(schema, data, opts = {})
|
286
|
+
fully_validate(schema, data, opts.merge(json: true))
|
282
287
|
end
|
283
288
|
|
284
|
-
def fully_validate_uri(schema, data, opts={})
|
285
|
-
fully_validate(schema, data, opts.merge(:
|
289
|
+
def fully_validate_uri(schema, data, opts = {})
|
290
|
+
fully_validate(schema, data, opts.merge(uri: true))
|
286
291
|
end
|
287
292
|
|
288
293
|
def schema_reader
|
@@ -295,7 +300,6 @@ module JSON
|
|
295
300
|
|
296
301
|
def clear_cache
|
297
302
|
@@schemas = {}
|
298
|
-
JSON::Util::URI.clear_cache
|
299
303
|
end
|
300
304
|
|
301
305
|
def schemas
|
@@ -322,7 +326,7 @@ module JSON
|
|
322
326
|
end
|
323
327
|
|
324
328
|
def cache_schemas=(val)
|
325
|
-
warn
|
329
|
+
warn '[DEPRECATION NOTICE] Schema caching is now a validation option. Schemas will still be cached if this is set to true, but this method will be removed in version >= 3. Please use the :clear_cache validation option instead.'
|
326
330
|
@@cache_schemas = val == true ? true : false
|
327
331
|
end
|
328
332
|
|
@@ -334,32 +338,34 @@ module JSON
|
|
334
338
|
@@default_validator
|
335
339
|
end
|
336
340
|
|
337
|
-
def validator_for_uri(schema_uri, raise_not_found=true)
|
341
|
+
def validator_for_uri(schema_uri, raise_not_found = true)
|
338
342
|
return default_validator unless schema_uri
|
343
|
+
|
339
344
|
u = JSON::Util::URI.parse(schema_uri)
|
340
345
|
validator = validators["#{u.scheme}://#{u.host}#{u.path}"]
|
341
346
|
if validator.nil? && raise_not_found
|
342
|
-
raise JSON::Schema::SchemaError
|
347
|
+
raise JSON::Schema::SchemaError, "Schema not found: #{schema_uri}"
|
343
348
|
else
|
344
349
|
validator
|
345
350
|
end
|
346
351
|
end
|
347
352
|
|
348
|
-
def validator_for_name(schema_name, raise_not_found=true)
|
353
|
+
def validator_for_name(schema_name, raise_not_found = true)
|
349
354
|
return default_validator unless schema_name
|
355
|
+
|
350
356
|
schema_name = schema_name.to_s
|
351
357
|
validator = validators.values.detect do |v|
|
352
358
|
Array(v.names).include?(schema_name)
|
353
359
|
end
|
354
360
|
if validator.nil? && raise_not_found
|
355
|
-
raise JSON::Schema::SchemaError
|
361
|
+
raise JSON::Schema::SchemaError, 'The requested JSON schema version is not supported'
|
356
362
|
else
|
357
363
|
validator
|
358
364
|
end
|
359
365
|
end
|
360
366
|
|
361
367
|
def validator_for(schema_uri)
|
362
|
-
warn
|
368
|
+
warn '[DEPRECATION NOTICE] JSON::Validator#validator_for has been replaced by JSON::Validator#validator_for_uri and will be removed in version >= 3. Please use the #validator_for_uri method instead.'
|
363
369
|
validator_for_uri(schema_uri)
|
364
370
|
end
|
365
371
|
|
@@ -371,7 +377,7 @@ module JSON
|
|
371
377
|
@@default_validator = v
|
372
378
|
end
|
373
379
|
|
374
|
-
def register_format_validator(format, validation_proc, versions = (@@validators.flat_map{ |
|
380
|
+
def register_format_validator(format, validation_proc, versions = (@@validators.flat_map { |_k, v| v.names.first } + [nil]))
|
375
381
|
custom_format_validator = JSON::Schema::CustomFormat.new(validation_proc)
|
376
382
|
versions.each do |version|
|
377
383
|
validator = validator_for_name(version)
|
@@ -379,14 +385,14 @@ module JSON
|
|
379
385
|
end
|
380
386
|
end
|
381
387
|
|
382
|
-
def deregister_format_validator(format, versions = (@@validators.flat_map{ |
|
388
|
+
def deregister_format_validator(format, versions = (@@validators.flat_map { |_k, v| v.names.first } + [nil]))
|
383
389
|
versions.each do |version|
|
384
390
|
validator = validator_for_name(version)
|
385
391
|
validator.formats[format.to_s] = validator.default_formats[format.to_s]
|
386
392
|
end
|
387
393
|
end
|
388
394
|
|
389
|
-
def restore_default_formats(versions = (@@validators.flat_map{ |
|
395
|
+
def restore_default_formats(versions = (@@validators.flat_map { |_k, v| v.names.first } + [nil]))
|
390
396
|
versions.each do |version|
|
391
397
|
validator = validator_for_name(version)
|
392
398
|
validator.formats = validator.default_formats.clone
|
@@ -410,7 +416,7 @@ module JSON
|
|
410
416
|
if @@available_json_backends.include?(backend)
|
411
417
|
@@json_backend = backend
|
412
418
|
else
|
413
|
-
raise JSON::Schema::JsonParseError
|
419
|
+
raise JSON::Schema::JsonParseError, "The JSON backend '#{backend}' could not be found."
|
414
420
|
end
|
415
421
|
end
|
416
422
|
end
|
@@ -420,26 +426,26 @@ module JSON
|
|
420
426
|
begin
|
421
427
|
MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
|
422
428
|
rescue MultiJson::ParseError => e
|
423
|
-
raise JSON::Schema::JsonParseError
|
429
|
+
raise JSON::Schema::JsonParseError, e.message
|
424
430
|
end
|
425
431
|
else
|
426
432
|
case @@json_backend.to_s
|
427
433
|
when 'json'
|
428
434
|
begin
|
429
|
-
JSON.parse(s, :
|
435
|
+
JSON.parse(s, quirks_mode: true)
|
430
436
|
rescue JSON::ParserError => e
|
431
|
-
raise JSON::Schema::JsonParseError
|
437
|
+
raise JSON::Schema::JsonParseError, e.message
|
432
438
|
end
|
433
439
|
when 'yajl'
|
434
440
|
begin
|
435
441
|
json = StringIO.new(s)
|
436
442
|
parser = Yajl::Parser.new
|
437
|
-
parser.parse(json) or raise
|
443
|
+
parser.parse(json) or raise(JSON::Schema::JsonParseError, 'The JSON could not be parsed by yajl')
|
438
444
|
rescue Yajl::ParseError => e
|
439
|
-
raise JSON::Schema::JsonParseError
|
445
|
+
raise JSON::Schema::JsonParseError, e.message
|
440
446
|
end
|
441
447
|
else
|
442
|
-
raise JSON::Schema::JsonParseError
|
448
|
+
raise JSON::Schema::JsonParseError, "No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json"
|
443
449
|
end
|
444
450
|
end
|
445
451
|
end
|
@@ -478,7 +484,6 @@ module JSON
|
|
478
484
|
end
|
479
485
|
end
|
480
486
|
|
481
|
-
|
482
487
|
if Gem::Specification::find_all_by_name('yajl-ruby').any?
|
483
488
|
require 'yajl'
|
484
489
|
@@available_json_backends << 'yajl'
|
@@ -486,11 +491,11 @@ module JSON
|
|
486
491
|
end
|
487
492
|
|
488
493
|
if @@json_backend == 'yajl'
|
489
|
-
@@serializer = lambda{|o| Yajl::Encoder.encode(o) }
|
494
|
+
@@serializer = lambda { |o| Yajl::Encoder.encode(o) }
|
490
495
|
elsif @@json_backend == 'json'
|
491
|
-
@@serializer = lambda{|o| JSON.dump(o) }
|
496
|
+
@@serializer = lambda { |o| JSON.dump(o) }
|
492
497
|
else
|
493
|
-
@@serializer = lambda{|o| YAML.dump(o) }
|
498
|
+
@@serializer = lambda { |o| YAML.dump(o) }
|
494
499
|
end
|
495
500
|
end
|
496
501
|
end
|
@@ -499,10 +504,10 @@ module JSON
|
|
499
504
|
|
500
505
|
if Gem::Specification::find_all_by_name('uuidtools').any?
|
501
506
|
require 'uuidtools'
|
502
|
-
@@fake_uuid_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
|
507
|
+
@@fake_uuid_generator = lambda { |s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
|
503
508
|
else
|
504
509
|
require 'json-schema/util/uuid'
|
505
|
-
@@fake_uuid_generator = lambda{|s| JSON::Util::UUID.create_v5(s,JSON::Util::UUID::Nil).to_s }
|
510
|
+
@@fake_uuid_generator = lambda { |s| JSON::Util::UUID.create_v5(s, JSON::Util::UUID::Nil).to_s }
|
506
511
|
end
|
507
512
|
|
508
513
|
def serialize schema
|
@@ -517,12 +522,12 @@ module JSON
|
|
517
522
|
@@fake_uuid_generator.call(schema)
|
518
523
|
end
|
519
524
|
|
520
|
-
def initialize_schema(schema)
|
525
|
+
def initialize_schema(schema, default_validator)
|
521
526
|
if schema.is_a?(String)
|
522
527
|
begin
|
523
528
|
# Build a fake URI for this
|
524
529
|
schema_uri = JSON::Util::URI.parse(fake_uuid(schema))
|
525
|
-
schema = JSON::Schema.new(
|
530
|
+
schema = JSON::Schema.new(JSON::Validator.parse(schema), schema_uri, default_validator)
|
526
531
|
if @options[:list] && @options[:fragment].nil?
|
527
532
|
schema = schema.to_array_schema
|
528
533
|
end
|
@@ -552,13 +557,13 @@ module JSON
|
|
552
557
|
elsif schema.is_a?(Hash)
|
553
558
|
schema_uri = JSON::Util::URI.parse(fake_uuid(serialize(schema)))
|
554
559
|
schema = JSON::Schema.stringify(schema)
|
555
|
-
schema = JSON::Schema.new(schema, schema_uri,
|
560
|
+
schema = JSON::Schema.new(schema, schema_uri, default_validator)
|
556
561
|
if @options[:list] && @options[:fragment].nil?
|
557
562
|
schema = schema.to_array_schema
|
558
563
|
end
|
559
564
|
self.class.add_schema(schema)
|
560
565
|
else
|
561
|
-
raise JSON::Schema::SchemaParseError,
|
566
|
+
raise JSON::Schema::SchemaParseError, 'Invalid schema - must be either a string or a hash'
|
562
567
|
end
|
563
568
|
|
564
569
|
schema
|
@@ -573,12 +578,14 @@ module JSON
|
|
573
578
|
data = self.class.parse(custom_open(json_uri))
|
574
579
|
elsif data.is_a?(String)
|
575
580
|
begin
|
576
|
-
|
581
|
+
# Check if the string is valid integer
|
582
|
+
strict_convert = data.match?(/\A[+-]?\d+\z/) && !@options[:parse_integer]
|
583
|
+
data = strict_convert ? data : self.class.parse(data)
|
577
584
|
rescue JSON::Schema::JsonParseError
|
578
585
|
begin
|
579
586
|
json_uri = Util::URI.normalized_uri(data)
|
580
587
|
data = self.class.parse(custom_open(json_uri))
|
581
|
-
rescue JSON::Schema::JsonLoadError
|
588
|
+
rescue JSON::Schema::JsonLoadError, JSON::Schema::UriError
|
582
589
|
# Silently discard the error - use the data as-is
|
583
590
|
end
|
584
591
|
end
|
@@ -591,7 +598,7 @@ module JSON
|
|
591
598
|
uri = Util::URI.normalized_uri(uri) if uri.is_a?(String)
|
592
599
|
if uri.absolute? && Util::URI::SUPPORTED_PROTOCOLS.include?(uri.scheme)
|
593
600
|
begin
|
594
|
-
open(uri.to_s).read
|
601
|
+
URI.open(uri.to_s).read
|
595
602
|
rescue OpenURI::HTTPError, Timeout::Error => e
|
596
603
|
raise JSON::Schema::JsonLoadError, e.message
|
597
604
|
end
|
@@ -2,27 +2,26 @@ require 'json-schema/schema/validator'
|
|
2
2
|
|
3
3
|
module JSON
|
4
4
|
class Schema
|
5
|
-
|
6
5
|
class Draft1 < Validator
|
7
6
|
def initialize
|
8
7
|
super
|
9
8
|
@attributes = {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
9
|
+
'type' => JSON::Schema::TypeAttribute,
|
10
|
+
'disallow' => JSON::Schema::DisallowAttribute,
|
11
|
+
'format' => JSON::Schema::FormatAttribute,
|
12
|
+
'maximum' => JSON::Schema::MaximumInclusiveAttribute,
|
13
|
+
'minimum' => JSON::Schema::MinimumInclusiveAttribute,
|
14
|
+
'minItems' => JSON::Schema::MinItemsAttribute,
|
15
|
+
'maxItems' => JSON::Schema::MaxItemsAttribute,
|
16
|
+
'minLength' => JSON::Schema::MinLengthAttribute,
|
17
|
+
'maxLength' => JSON::Schema::MaxLengthAttribute,
|
18
|
+
'maxDecimal' => JSON::Schema::MaxDecimalAttribute,
|
19
|
+
'enum' => JSON::Schema::EnumAttribute,
|
20
|
+
'properties' => JSON::Schema::PropertiesOptionalAttribute,
|
21
|
+
'pattern' => JSON::Schema::PatternAttribute,
|
22
|
+
'additionalProperties' => JSON::Schema::AdditionalPropertiesAttribute,
|
23
|
+
'items' => JSON::Schema::ItemsAttribute,
|
24
|
+
'extends' => JSON::Schema::ExtendsAttribute,
|
26
25
|
}
|
27
26
|
@default_formats = {
|
28
27
|
'date-time' => DateTimeFormat,
|
@@ -30,16 +29,15 @@ module JSON
|
|
30
29
|
'time' => TimeFormat,
|
31
30
|
'ip-address' => IP4Format,
|
32
31
|
'ipv6' => IP6Format,
|
33
|
-
'uri' => UriFormat
|
32
|
+
'uri' => UriFormat,
|
34
33
|
}
|
35
34
|
@formats = @default_formats.clone
|
36
|
-
@uri = JSON::Util::URI.parse(
|
37
|
-
@names = [
|
38
|
-
@metaschema_name =
|
35
|
+
@uri = JSON::Util::URI.parse('http://json-schema.org/draft-01/schema#')
|
36
|
+
@names = ['draft1']
|
37
|
+
@metaschema_name = 'draft-01.json'
|
39
38
|
end
|
40
39
|
|
41
|
-
JSON::Validator.register_validator(
|
40
|
+
JSON::Validator.register_validator(new)
|
42
41
|
end
|
43
|
-
|
44
42
|
end
|
45
43
|
end
|