json-schema-ouidou 2.9.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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +19 -0
  3. data/README.md +496 -0
  4. data/lib/json-schema/attribute.rb +57 -0
  5. data/lib/json-schema/attributes/additionalitems.rb +28 -0
  6. data/lib/json-schema/attributes/additionalproperties.rb +58 -0
  7. data/lib/json-schema/attributes/allof.rb +39 -0
  8. data/lib/json-schema/attributes/anyof.rb +47 -0
  9. data/lib/json-schema/attributes/dependencies.rb +38 -0
  10. data/lib/json-schema/attributes/dependencies_v4.rb +11 -0
  11. data/lib/json-schema/attributes/disallow.rb +12 -0
  12. data/lib/json-schema/attributes/divisibleby.rb +22 -0
  13. data/lib/json-schema/attributes/enum.rb +24 -0
  14. data/lib/json-schema/attributes/extends.rb +48 -0
  15. data/lib/json-schema/attributes/format.rb +14 -0
  16. data/lib/json-schema/attributes/formats/custom.rb +21 -0
  17. data/lib/json-schema/attributes/formats/date.rb +25 -0
  18. data/lib/json-schema/attributes/formats/date_time.rb +34 -0
  19. data/lib/json-schema/attributes/formats/date_time_v4.rb +15 -0
  20. data/lib/json-schema/attributes/formats/ip.rb +41 -0
  21. data/lib/json-schema/attributes/formats/time.rb +22 -0
  22. data/lib/json-schema/attributes/formats/uri.rb +18 -0
  23. data/lib/json-schema/attributes/items.rb +27 -0
  24. data/lib/json-schema/attributes/limit.rb +52 -0
  25. data/lib/json-schema/attributes/limits/items.rb +15 -0
  26. data/lib/json-schema/attributes/limits/length.rb +15 -0
  27. data/lib/json-schema/attributes/limits/max_items.rb +15 -0
  28. data/lib/json-schema/attributes/limits/max_length.rb +15 -0
  29. data/lib/json-schema/attributes/limits/max_properties.rb +15 -0
  30. data/lib/json-schema/attributes/limits/maximum.rb +15 -0
  31. data/lib/json-schema/attributes/limits/maximum_inclusive.rb +11 -0
  32. data/lib/json-schema/attributes/limits/min_items.rb +15 -0
  33. data/lib/json-schema/attributes/limits/min_length.rb +15 -0
  34. data/lib/json-schema/attributes/limits/min_properties.rb +15 -0
  35. data/lib/json-schema/attributes/limits/minimum.rb +15 -0
  36. data/lib/json-schema/attributes/limits/minimum_inclusive.rb +11 -0
  37. data/lib/json-schema/attributes/limits/numeric.rb +16 -0
  38. data/lib/json-schema/attributes/limits/properties.rb +15 -0
  39. data/lib/json-schema/attributes/maxdecimal.rb +18 -0
  40. data/lib/json-schema/attributes/multipleof.rb +11 -0
  41. data/lib/json-schema/attributes/not.rb +30 -0
  42. data/lib/json-schema/attributes/oneof.rb +56 -0
  43. data/lib/json-schema/attributes/pattern.rb +18 -0
  44. data/lib/json-schema/attributes/patternproperties.rb +22 -0
  45. data/lib/json-schema/attributes/properties.rb +66 -0
  46. data/lib/json-schema/attributes/properties_optional.rb +26 -0
  47. data/lib/json-schema/attributes/properties_v4.rb +13 -0
  48. data/lib/json-schema/attributes/ref.rb +61 -0
  49. data/lib/json-schema/attributes/required.rb +28 -0
  50. data/lib/json-schema/attributes/type.rb +73 -0
  51. data/lib/json-schema/attributes/type_v4.rb +29 -0
  52. data/lib/json-schema/attributes/uniqueitems.rb +20 -0
  53. data/lib/json-schema/errors/custom_format_error.rb +6 -0
  54. data/lib/json-schema/errors/json_load_error.rb +6 -0
  55. data/lib/json-schema/errors/json_parse_error.rb +6 -0
  56. data/lib/json-schema/errors/schema_error.rb +6 -0
  57. data/lib/json-schema/errors/schema_parse_error.rb +8 -0
  58. data/lib/json-schema/errors/uri_error.rb +6 -0
  59. data/lib/json-schema/errors/validation_error.rb +46 -0
  60. data/lib/json-schema/schema/reader.rb +140 -0
  61. data/lib/json-schema/schema/validator.rb +40 -0
  62. data/lib/json-schema/schema.rb +62 -0
  63. data/lib/json-schema/util/array_set.rb +20 -0
  64. data/lib/json-schema/util/uri.rb +110 -0
  65. data/lib/json-schema/util/uuid.rb +284 -0
  66. data/lib/json-schema/validator.rb +609 -0
  67. data/lib/json-schema/validators/draft1.rb +45 -0
  68. data/lib/json-schema/validators/draft2.rb +46 -0
  69. data/lib/json-schema/validators/draft3.rb +50 -0
  70. data/lib/json-schema/validators/draft4.rb +56 -0
  71. data/lib/json-schema/validators/draft6.rb +56 -0
  72. data/lib/json-schema/validators/hyper-draft1.rb +13 -0
  73. data/lib/json-schema/validators/hyper-draft2.rb +13 -0
  74. data/lib/json-schema/validators/hyper-draft3.rb +13 -0
  75. data/lib/json-schema/validators/hyper-draft4.rb +13 -0
  76. data/lib/json-schema/validators/hyper-draft6.rb +13 -0
  77. data/lib/json-schema.rb +18 -0
  78. data/resources/draft-01.json +155 -0
  79. data/resources/draft-02.json +166 -0
  80. data/resources/draft-03.json +174 -0
  81. data/resources/draft-04.json +150 -0
  82. data/resources/draft-06.json +150 -0
  83. metadata +197 -0
@@ -0,0 +1,609 @@
1
+ require 'open-uri'
2
+ require 'pathname'
3
+ require 'bigdecimal'
4
+ require 'digest/sha1'
5
+ require 'date'
6
+ require 'thread'
7
+ require 'yaml'
8
+
9
+ require 'json-schema/schema/reader'
10
+ require 'json-schema/errors/schema_error'
11
+ require 'json-schema/errors/schema_parse_error'
12
+ require 'json-schema/errors/json_load_error'
13
+ require 'json-schema/errors/json_parse_error'
14
+ require 'json-schema/util/uri'
15
+
16
+ module JSON
17
+
18
+ class Validator
19
+
20
+ @@schemas = {}
21
+ @@cache_schemas = true
22
+ @@default_opts = {
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
+ :parse_data => true
32
+ }
33
+ @@validators = {}
34
+ @@default_validator = nil
35
+ @@available_json_backends = []
36
+ @@json_backend = nil
37
+ @@serializer = nil
38
+ @@mutex = Mutex.new
39
+
40
+ def initialize(schema_data, data, opts={})
41
+ @options = @@default_opts.clone.merge(opts)
42
+ @errors = []
43
+
44
+ validator = self.class.validator_for_name(@options[:version])
45
+ @options[:version] = validator
46
+ @options[:schema_reader] ||= self.class.schema_reader
47
+
48
+ @validation_options = @options[:record_errors] ? {:record_errors => true} : {}
49
+ @validation_options[:insert_defaults] = true if @options[:insert_defaults]
50
+ @validation_options[:strict] = true if @options[:strict] == true
51
+ @validation_options[:clear_cache] = true if !@@cache_schemas || @options[:clear_cache]
52
+
53
+ @@mutex.synchronize { @base_schema = initialize_schema(schema_data) }
54
+ @original_data = data
55
+ @data = initialize_data(data)
56
+ @@mutex.synchronize { build_schemas(@base_schema) }
57
+
58
+ # validate the schema, if requested
59
+ 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
+ # Don't clear the cache during metaschema validation!
65
+ self.class.validate!(metaschema, @base_schema.schema, {:clear_cache => false})
66
+ end
67
+
68
+ # If the :fragment option is set, try and validate against the fragment
69
+ if opts[:fragment]
70
+ @base_schema = schema_from_fragment(@base_schema, opts[:fragment])
71
+ end
72
+ end
73
+
74
+ def schema_from_fragment(base_schema, fragment)
75
+ schema_uri = base_schema.uri
76
+ fragments = fragment.split("/")
77
+
78
+ # ensure the first element was a hash, per the fragment spec
79
+ if fragments.shift != "#"
80
+ raise JSON::Schema::SchemaError.new("Invalid fragment syntax in :fragment option")
81
+ end
82
+
83
+ fragments.each do |f|
84
+ if base_schema.is_a?(JSON::Schema) #test if fragment is a JSON:Schema instance
85
+ if !base_schema.schema.has_key?(f)
86
+ raise JSON::Schema::SchemaError.new("Invalid fragment resolution for :fragment option")
87
+ end
88
+ base_schema = base_schema.schema[f]
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")
101
+ end
102
+ end
103
+
104
+ if @options[:list]
105
+ base_schema.to_array_schema
106
+ elsif base_schema.is_a?(Hash)
107
+ JSON::Schema.new(base_schema, schema_uri, @options[:version])
108
+ else
109
+ base_schema
110
+ end
111
+ end
112
+
113
+ # Run a simple true/false validation of data against a schema
114
+ def validate
115
+ @base_schema.validate(@data,[],self,@validation_options)
116
+
117
+ if @options[:record_errors]
118
+ if @options[:errors_as_objects]
119
+ @errors.map{|e| e.to_hash}
120
+ else
121
+ @errors.map{|e| e.to_string}
122
+ end
123
+ else
124
+ true
125
+ end
126
+ ensure
127
+ if @validation_options[:clear_cache] == true
128
+ self.class.clear_cache
129
+ end
130
+ if @validation_options[:insert_defaults]
131
+ self.class.merge_missing_values(@data, @original_data)
132
+ end
133
+ end
134
+
135
+ def load_ref_schema(parent_schema, ref)
136
+ schema_uri = JSON::Util::URI.absolutize_ref(ref, parent_schema.uri)
137
+ return true if self.class.schema_loaded?(schema_uri)
138
+
139
+ validator = self.class.validator_for_uri(schema_uri, false)
140
+ schema_uri = JSON::Util::URI.file_uri(validator.metaschema) if validator
141
+
142
+ schema = @options[:schema_reader].read(schema_uri)
143
+ self.class.add_schema(schema)
144
+ build_schemas(schema)
145
+ end
146
+
147
+ # Build all schemas with IDs, mapping out the namespace
148
+ def build_schemas(parent_schema)
149
+ schema = parent_schema.schema
150
+
151
+ # Build ref schemas if they exist
152
+ if schema["$ref"]
153
+ load_ref_schema(parent_schema, schema["$ref"])
154
+ end
155
+
156
+ case schema["extends"]
157
+ when String
158
+ load_ref_schema(parent_schema, schema["extends"])
159
+ when Array
160
+ schema['extends'].each do |type|
161
+ handle_schema(parent_schema, type)
162
+ end
163
+ end
164
+
165
+ # Check for schemas in union types
166
+ ["type", "disallow"].each do |key|
167
+ if schema[key].is_a?(Array)
168
+ schema[key].each do |type|
169
+ if type.is_a?(Hash)
170
+ handle_schema(parent_schema, type)
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ # Schema properties whose values are objects, the values of which
177
+ # are themselves schemas.
178
+ %w[definitions properties patternProperties].each do |key|
179
+ next unless value = schema[key]
180
+ value.each do |k, inner_schema|
181
+ handle_schema(parent_schema, inner_schema)
182
+ end
183
+ end
184
+
185
+ # Schema properties whose values are themselves schemas.
186
+ %w[additionalProperties additionalItems dependencies extends].each do |key|
187
+ next unless schema[key].is_a?(Hash)
188
+ handle_schema(parent_schema, schema[key])
189
+ end
190
+
191
+ # Schema properties whose values may be an array of schemas.
192
+ %w[allOf anyOf oneOf not].each do |key|
193
+ next unless value = schema[key]
194
+ Array(value).each do |inner_schema|
195
+ handle_schema(parent_schema, inner_schema)
196
+ end
197
+ end
198
+
199
+ # Items are always schemas
200
+ if schema["items"]
201
+ items = schema["items"].clone
202
+ items = [items] unless items.is_a?(Array)
203
+
204
+ items.each do |item|
205
+ handle_schema(parent_schema, item)
206
+ end
207
+ end
208
+
209
+ # Convert enum to a ArraySet
210
+ if schema["enum"].is_a?(Array)
211
+ schema["enum"] = ArraySet.new(schema["enum"])
212
+ end
213
+
214
+ end
215
+
216
+ # Either load a reference schema or create a new schema
217
+ def handle_schema(parent_schema, obj)
218
+ if obj.is_a?(Hash)
219
+ schema_uri = parent_schema.uri.dup
220
+ schema = JSON::Schema.new(obj, schema_uri, parent_schema.validator)
221
+ if obj['id']
222
+ self.class.add_schema(schema)
223
+ end
224
+ build_schemas(schema)
225
+ end
226
+ end
227
+
228
+ def validation_error(error)
229
+ @errors.push(error)
230
+ end
231
+
232
+ def validation_errors
233
+ @errors
234
+ end
235
+
236
+
237
+ class << self
238
+ def validate(schema, data,opts={})
239
+ begin
240
+ validate!(schema, data, opts)
241
+ rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
242
+ return false
243
+ end
244
+ end
245
+
246
+ def validate_json(schema, data, opts={})
247
+ validate(schema, data, opts.merge(:json => true))
248
+ end
249
+
250
+ def validate_uri(schema, data, opts={})
251
+ validate(schema, data, opts.merge(:uri => true))
252
+ end
253
+
254
+ def validate!(schema, data,opts={})
255
+ validator = new(schema, data, opts)
256
+ validator.validate
257
+ end
258
+
259
+ def validate2(schema, data, opts={})
260
+ 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."
261
+ validate!(schema, data, opts)
262
+ end
263
+
264
+ def validate_json!(schema, data, opts={})
265
+ validate!(schema, data, opts.merge(:json => true))
266
+ end
267
+
268
+ def validate_uri!(schema, data, opts={})
269
+ validate!(schema, data, opts.merge(:uri => true))
270
+ end
271
+
272
+ def fully_validate(schema, data, opts={})
273
+ validate!(schema, data, opts.merge(:record_errors => true))
274
+ end
275
+
276
+ def fully_validate_schema(schema, opts={})
277
+ data = schema
278
+ schema = validator_for_name(opts[:version]).metaschema
279
+ fully_validate(schema, data, opts)
280
+ end
281
+
282
+ def fully_validate_json(schema, data, opts={})
283
+ fully_validate(schema, data, opts.merge(:json => true))
284
+ end
285
+
286
+ def fully_validate_uri(schema, data, opts={})
287
+ fully_validate(schema, data, opts.merge(:uri => true))
288
+ end
289
+
290
+ def schema_reader
291
+ @@schema_reader ||= JSON::Schema::Reader.new
292
+ end
293
+
294
+ def schema_reader=(reader)
295
+ @@schema_reader = reader
296
+ end
297
+
298
+ def clear_cache
299
+ @@schemas = {}
300
+ JSON::Util::URI.clear_cache
301
+ end
302
+
303
+ def schemas
304
+ @@schemas
305
+ end
306
+
307
+ def add_schema(schema)
308
+ @@schemas[schema_key_for(schema.uri)] ||= schema
309
+ end
310
+
311
+ def schema_for_uri(uri)
312
+ # We only store normalized uris terminated with fragment #, so we can try whether
313
+ # normalization can be skipped
314
+ @@schemas[uri] || @@schemas[schema_key_for(uri)]
315
+ end
316
+
317
+ def schema_loaded?(schema_uri)
318
+ !schema_for_uri(schema_uri).nil?
319
+ end
320
+
321
+ def schema_key_for(uri)
322
+ key = Util::URI.normalized_uri(uri).to_s
323
+ key.end_with?('#') ? key : "#{key}#"
324
+ end
325
+
326
+ def cache_schemas=(val)
327
+ 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."
328
+ @@cache_schemas = val == true ? true : false
329
+ end
330
+
331
+ def validators
332
+ @@validators
333
+ end
334
+
335
+ def default_validator
336
+ @@default_validator
337
+ end
338
+
339
+ def validator_for_uri(schema_uri, raise_not_found=true)
340
+ return default_validator unless schema_uri
341
+ u = JSON::Util::URI.parse(schema_uri)
342
+ validator = validators["#{u.scheme}://#{u.host}#{u.path}"]
343
+ if validator.nil? && raise_not_found
344
+ raise JSON::Schema::SchemaError.new("Schema not found: #{schema_uri}")
345
+ else
346
+ validator
347
+ end
348
+ end
349
+
350
+ def validator_for_name(schema_name, raise_not_found=true)
351
+ return default_validator unless schema_name
352
+ schema_name = schema_name.to_s
353
+ validator = validators.values.detect do |v|
354
+ Array(v.names).include?(schema_name)
355
+ end
356
+ if validator.nil? && raise_not_found
357
+ raise JSON::Schema::SchemaError.new("The requested JSON schema version is not supported")
358
+ else
359
+ validator
360
+ end
361
+ end
362
+
363
+ def validator_for(schema_uri)
364
+ 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."
365
+ validator_for_uri(schema_uri)
366
+ end
367
+
368
+ def register_validator(v)
369
+ @@validators["#{v.uri.scheme}://#{v.uri.host}#{v.uri.path}"] = v
370
+ end
371
+
372
+ def register_default_validator(v)
373
+ @@default_validator = v
374
+ end
375
+
376
+ def register_format_validator(format, validation_proc, versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil]))
377
+ custom_format_validator = JSON::Schema::CustomFormat.new(validation_proc)
378
+ versions.each do |version|
379
+ validator = validator_for_name(version)
380
+ validator.formats[format.to_s] = custom_format_validator
381
+ end
382
+ end
383
+
384
+ def deregister_format_validator(format, versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil]))
385
+ versions.each do |version|
386
+ validator = validator_for_name(version)
387
+ validator.formats[format.to_s] = validator.default_formats[format.to_s]
388
+ end
389
+ end
390
+
391
+ def restore_default_formats(versions = (@@validators.flat_map{ |k, v| v.names.first } + [nil]))
392
+ versions.each do |version|
393
+ validator = validator_for_name(version)
394
+ validator.formats = validator.default_formats.clone
395
+ end
396
+ end
397
+
398
+ def json_backend
399
+ if defined?(MultiJson)
400
+ MultiJson.respond_to?(:adapter) ? MultiJson.adapter : MultiJson.engine
401
+ else
402
+ @@json_backend
403
+ end
404
+ end
405
+
406
+ def json_backend=(backend)
407
+ if defined?(MultiJson)
408
+ backend = backend == 'json' ? 'json_gem' : backend
409
+ MultiJson.respond_to?(:use) ? MultiJson.use(backend) : MultiJson.engine = backend
410
+ else
411
+ backend = backend.to_s
412
+ if @@available_json_backends.include?(backend)
413
+ @@json_backend = backend
414
+ else
415
+ raise JSON::Schema::JsonParseError.new("The JSON backend '#{backend}' could not be found.")
416
+ end
417
+ end
418
+ end
419
+
420
+ def parse(s)
421
+ if defined?(MultiJson)
422
+ begin
423
+ MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
424
+ rescue MultiJson::ParseError => e
425
+ raise JSON::Schema::JsonParseError.new(e.message)
426
+ end
427
+ else
428
+ case @@json_backend.to_s
429
+ when 'json'
430
+ begin
431
+ JSON.parse(s, :quirks_mode => true)
432
+ rescue JSON::ParserError => e
433
+ raise JSON::Schema::JsonParseError.new(e.message)
434
+ end
435
+ when 'yajl'
436
+ begin
437
+ json = StringIO.new(s)
438
+ parser = Yajl::Parser.new
439
+ parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl")
440
+ rescue Yajl::ParseError => e
441
+ raise JSON::Schema::JsonParseError.new(e.message)
442
+ end
443
+ else
444
+ raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json")
445
+ end
446
+ end
447
+ end
448
+
449
+ def merge_missing_values(source, destination)
450
+ case destination
451
+ when Hash
452
+ source.each do |key, source_value|
453
+ destination_value = destination[key] || destination[key.to_sym]
454
+ if destination_value.nil?
455
+ destination[key] = source_value
456
+ else
457
+ merge_missing_values(source_value, destination_value)
458
+ end
459
+ end
460
+ when Array
461
+ source.each_with_index do |source_value, i|
462
+ destination_value = destination[i]
463
+ merge_missing_values(source_value, destination_value)
464
+ end
465
+ end
466
+ end
467
+
468
+ if !defined?(MultiJson)
469
+ if Gem::Specification::find_all_by_name('json').any?
470
+ require 'json'
471
+ @@available_json_backends << 'json'
472
+ @@json_backend = 'json'
473
+ else
474
+ # Try force-loading json for rubies > 1.9.2
475
+ begin
476
+ require 'json'
477
+ @@available_json_backends << 'json'
478
+ @@json_backend = 'json'
479
+ rescue LoadError
480
+ end
481
+ end
482
+
483
+
484
+ if Gem::Specification::find_all_by_name('yajl-ruby').any?
485
+ require 'yajl'
486
+ @@available_json_backends << 'yajl'
487
+ @@json_backend = 'yajl'
488
+ end
489
+
490
+ if @@json_backend == 'yajl'
491
+ @@serializer = lambda{|o| Yajl::Encoder.encode(o) }
492
+ elsif @@json_backend == 'json'
493
+ @@serializer = lambda{|o| JSON.dump(o) }
494
+ else
495
+ @@serializer = lambda{|o| YAML.dump(o) }
496
+ end
497
+ end
498
+ end
499
+
500
+ private
501
+
502
+ if Gem::Specification::find_all_by_name('uuidtools').any?
503
+ require 'uuidtools'
504
+ @@fake_uuid_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s }
505
+ else
506
+ require 'json-schema/util/uuid'
507
+ @@fake_uuid_generator = lambda{|s| JSON::Util::UUID.create_v5(s,JSON::Util::UUID::Nil).to_s }
508
+ end
509
+
510
+ def serialize schema
511
+ if defined?(MultiJson)
512
+ MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema)
513
+ else
514
+ @@serializer.call(schema)
515
+ end
516
+ end
517
+
518
+ def fake_uuid schema
519
+ @@fake_uuid_generator.call(schema)
520
+ end
521
+
522
+ def initialize_schema(schema)
523
+ if schema.is_a?(String)
524
+ begin
525
+ # Build a fake URI for this
526
+ schema_uri = JSON::Util::URI.parse(fake_uuid(schema))
527
+ schema = JSON::Schema.new(self.class.parse(schema), schema_uri, @options[:version])
528
+ if @options[:list] && @options[:fragment].nil?
529
+ schema = schema.to_array_schema
530
+ end
531
+ self.class.add_schema(schema)
532
+ rescue JSON::Schema::JsonParseError
533
+ # Build a uri for it
534
+ schema_uri = Util::URI.normalized_uri(schema)
535
+ if !self.class.schema_loaded?(schema_uri)
536
+ schema = @options[:schema_reader].read(schema_uri)
537
+ schema = JSON::Schema.stringify(schema)
538
+
539
+ if @options[:list] && @options[:fragment].nil?
540
+ schema = schema.to_array_schema
541
+ end
542
+
543
+ self.class.add_schema(schema)
544
+ else
545
+ schema = self.class.schema_for_uri(schema_uri)
546
+ if @options[:list] && @options[:fragment].nil?
547
+ schema = schema.to_array_schema
548
+ schema.uri = JSON::Util::URI.parse(fake_uuid(serialize(schema.schema)))
549
+ self.class.add_schema(schema)
550
+ end
551
+ schema
552
+ end
553
+ end
554
+ elsif schema.is_a?(Hash)
555
+ schema_uri = JSON::Util::URI.parse(fake_uuid(serialize(schema)))
556
+ schema = JSON::Schema.stringify(schema)
557
+ schema = JSON::Schema.new(schema, schema_uri, @options[:version])
558
+ if @options[:list] && @options[:fragment].nil?
559
+ schema = schema.to_array_schema
560
+ end
561
+ self.class.add_schema(schema)
562
+ else
563
+ raise JSON::Schema::SchemaParseError, "Invalid schema - must be either a string or a hash"
564
+ end
565
+
566
+ schema
567
+ end
568
+
569
+ def initialize_data(data)
570
+ if @options[:parse_data]
571
+ if @options[:json]
572
+ data = self.class.parse(data)
573
+ elsif @options[:uri]
574
+ json_uri = Util::URI.normalized_uri(data)
575
+ data = self.class.parse(custom_open(json_uri))
576
+ elsif data.is_a?(String)
577
+ begin
578
+ data = self.class.parse(data)
579
+ rescue JSON::Schema::JsonParseError
580
+ begin
581
+ json_uri = Util::URI.normalized_uri(data)
582
+ data = self.class.parse(custom_open(json_uri))
583
+ rescue JSON::Schema::JsonLoadError, JSON::Schema::UriError
584
+ # Silently discard the error - use the data as-is
585
+ end
586
+ end
587
+ end
588
+ end
589
+ JSON::Schema.stringify(data)
590
+ end
591
+
592
+ def custom_open(uri)
593
+ uri = Util::URI.normalized_uri(uri) if uri.is_a?(String)
594
+ if uri.absolute? && Util::URI::SUPPORTED_PROTOCOLS.include?(uri.scheme)
595
+ begin
596
+ open(uri.to_s).read
597
+ rescue OpenURI::HTTPError, Timeout::Error => e
598
+ raise JSON::Schema::JsonLoadError, e.message
599
+ end
600
+ else
601
+ begin
602
+ File.read(JSON::Util::URI.unescaped_path(uri))
603
+ rescue SystemCallError => e
604
+ raise JSON::Schema::JsonLoadError, e.message
605
+ end
606
+ end
607
+ end
608
+ end
609
+ end
@@ -0,0 +1,45 @@
1
+ require 'json-schema/schema/validator'
2
+
3
+ module JSON
4
+ class Schema
5
+
6
+ class Draft1 < Validator
7
+ def initialize
8
+ super
9
+ @attributes = {
10
+ "type" => JSON::Schema::TypeAttribute,
11
+ "disallow" => JSON::Schema::DisallowAttribute,
12
+ "format" => JSON::Schema::FormatAttribute,
13
+ "maximum" => JSON::Schema::MaximumInclusiveAttribute,
14
+ "minimum" => JSON::Schema::MinimumInclusiveAttribute,
15
+ "minItems" => JSON::Schema::MinItemsAttribute,
16
+ "maxItems" => JSON::Schema::MaxItemsAttribute,
17
+ "minLength" => JSON::Schema::MinLengthAttribute,
18
+ "maxLength" => JSON::Schema::MaxLengthAttribute,
19
+ "maxDecimal" => JSON::Schema::MaxDecimalAttribute,
20
+ "enum" => JSON::Schema::EnumAttribute,
21
+ "properties" => JSON::Schema::PropertiesOptionalAttribute,
22
+ "pattern" => JSON::Schema::PatternAttribute,
23
+ "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute,
24
+ "items" => JSON::Schema::ItemsAttribute,
25
+ "extends" => JSON::Schema::ExtendsAttribute
26
+ }
27
+ @default_formats = {
28
+ 'date-time' => DateTimeFormat,
29
+ 'date' => DateFormat,
30
+ 'time' => TimeFormat,
31
+ 'ip-address' => IP4Format,
32
+ 'ipv6' => IP6Format,
33
+ 'uri' => UriFormat
34
+ }
35
+ @formats = @default_formats.clone
36
+ @uri = JSON::Util::URI.parse("http://json-schema.org/draft-01/schema#")
37
+ @names = ["draft1"]
38
+ @metaschema_name = "draft-01.json"
39
+ end
40
+
41
+ JSON::Validator.register_validator(self.new)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ require 'json-schema/schema/validator'
2
+
3
+ module JSON
4
+ class Schema
5
+
6
+ class Draft2 < Validator
7
+ def initialize
8
+ super
9
+ @attributes = {
10
+ "type" => JSON::Schema::TypeAttribute,
11
+ "disallow" => JSON::Schema::DisallowAttribute,
12
+ "format" => JSON::Schema::FormatAttribute,
13
+ "maximum" => JSON::Schema::MaximumInclusiveAttribute,
14
+ "minimum" => JSON::Schema::MinimumInclusiveAttribute,
15
+ "minItems" => JSON::Schema::MinItemsAttribute,
16
+ "maxItems" => JSON::Schema::MaxItemsAttribute,
17
+ "uniqueItems" => JSON::Schema::UniqueItemsAttribute,
18
+ "minLength" => JSON::Schema::MinLengthAttribute,
19
+ "maxLength" => JSON::Schema::MaxLengthAttribute,
20
+ "divisibleBy" => JSON::Schema::DivisibleByAttribute,
21
+ "enum" => JSON::Schema::EnumAttribute,
22
+ "properties" => JSON::Schema::PropertiesOptionalAttribute,
23
+ "pattern" => JSON::Schema::PatternAttribute,
24
+ "additionalProperties" => JSON::Schema::AdditionalPropertiesAttribute,
25
+ "items" => JSON::Schema::ItemsAttribute,
26
+ "extends" => JSON::Schema::ExtendsAttribute
27
+ }
28
+ @default_formats = {
29
+ 'date-time' => DateTimeFormat,
30
+ 'date' => DateFormat,
31
+ 'time' => TimeFormat,
32
+ 'ip-address' => IP4Format,
33
+ 'ipv6' => IP6Format,
34
+ 'uri' => UriFormat
35
+ }
36
+ @formats = @default_formats.clone
37
+ @uri = JSON::Util::URI.parse("http://json-schema.org/draft-02/schema#")
38
+ @names = ["draft2"]
39
+ @metaschema_name = "draft-02.json"
40
+ end
41
+
42
+ JSON::Validator.register_validator(self.new)
43
+ end
44
+
45
+ end
46
+ end