json-schema-openc-fork 0.0.1

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