json-schema 2.4.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +6 -14
  2. data/README.textile +58 -7
  3. data/lib/json-schema.rb +3 -1
  4. data/lib/json-schema/attributes/additionalitems.rb +14 -11
  5. data/lib/json-schema/attributes/additionalproperties.rb +33 -43
  6. data/lib/json-schema/attributes/anyof.rb +4 -0
  7. data/lib/json-schema/attributes/dependencies.rb +31 -19
  8. data/lib/json-schema/attributes/disallow.rb +2 -3
  9. data/lib/json-schema/attributes/divisibleby.rb +11 -7
  10. data/lib/json-schema/attributes/enum.rb +14 -16
  11. data/lib/json-schema/attributes/format.rb +4 -7
  12. data/lib/json-schema/attributes/formats/date_time_v4.rb +5 -8
  13. data/lib/json-schema/attributes/formats/ip.rb +41 -0
  14. data/lib/json-schema/attributes/formats/uri.rb +10 -8
  15. data/lib/json-schema/attributes/items.rb +15 -16
  16. data/lib/json-schema/attributes/limit.rb +179 -0
  17. data/lib/json-schema/attributes/maxdecimal.rb +7 -6
  18. data/lib/json-schema/attributes/multipleof.rb +4 -11
  19. data/lib/json-schema/attributes/not.rb +1 -1
  20. data/lib/json-schema/attributes/oneof.rb +15 -6
  21. data/lib/json-schema/attributes/pattern.rb +7 -6
  22. data/lib/json-schema/attributes/patternproperties.rb +9 -12
  23. data/lib/json-schema/attributes/properties.rb +55 -39
  24. data/lib/json-schema/attributes/properties_optional.rb +13 -12
  25. data/lib/json-schema/attributes/ref.rb +4 -4
  26. data/lib/json-schema/attributes/required.rb +16 -13
  27. data/lib/json-schema/attributes/type.rb +13 -18
  28. data/lib/json-schema/attributes/type_v4.rb +11 -18
  29. data/lib/json-schema/attributes/uniqueitems.rb +5 -7
  30. data/lib/json-schema/schema.rb +8 -8
  31. data/lib/json-schema/schema/#validator.rb# +37 -0
  32. data/lib/json-schema/schema/reader.rb +113 -0
  33. data/lib/json-schema/util/uri.rb +16 -0
  34. data/lib/json-schema/validator.rb +123 -128
  35. data/lib/json-schema/validators/draft1.rb +1 -1
  36. data/lib/json-schema/validators/draft2.rb +1 -1
  37. data/lib/json-schema/validators/draft3.rb +1 -1
  38. data/lib/json-schema/validators/draft4.rb +1 -1
  39. data/lib/json-schema/validators/hyper-draft4.rb +1 -1
  40. data/test/schemas/address_microformat.json +18 -0
  41. data/test/schemas/definition_schema.json +15 -0
  42. data/test/schemas/ref john with spaces schema.json +11 -0
  43. data/test/schemas/relative_definition_schema.json +8 -0
  44. data/test/test_all_of_ref_schema.rb +12 -15
  45. data/test/test_any_of_ref_schema.rb +7 -9
  46. data/test/test_bad_schema_ref.rb +18 -12
  47. data/test/test_common_test_suite.rb +45 -29
  48. data/test/test_custom_format.rb +2 -3
  49. data/test/test_definition.rb +15 -0
  50. data/test/test_extended_schema.rb +25 -31
  51. data/test/test_extends_and_additionalProperties.rb +23 -21
  52. data/test/test_files_v3.rb +14 -23
  53. data/test/test_fragment_resolution.rb +6 -7
  54. data/test/test_fragment_validation_with_ref.rb +2 -8
  55. data/test/test_full_validation.rb +2 -3
  56. data/test/test_helper.rb +46 -1
  57. data/test/test_initialize_data.rb +118 -0
  58. data/test/test_jsonschema_draft1.rb +48 -600
  59. data/test/test_jsonschema_draft2.rb +48 -699
  60. data/test/test_jsonschema_draft3.rb +91 -861
  61. data/test/test_jsonschema_draft4.rb +173 -812
  62. data/test/test_list_option.rb +6 -7
  63. data/test/{test_merge_misisng_values.rb → test_merge_missing_values.rb} +2 -3
  64. data/test/test_minitems.rb +2 -4
  65. data/test/test_one_of.rb +9 -19
  66. data/test/test_ruby_schema.rb +5 -14
  67. data/test/test_schema_loader.rb +74 -0
  68. data/test/test_schema_type_attribute.rb +2 -3
  69. data/test/test_schema_validation.rb +4 -5
  70. data/test/test_stringify.rb +2 -3
  71. data/test/test_uri_related.rb +67 -0
  72. data/test/test_validator.rb +53 -0
  73. metadata +129 -51
  74. data/lib/json-schema/attributes/dependencies_v4.rb +0 -27
  75. data/lib/json-schema/attributes/formats/ip4.rb +0 -20
  76. data/lib/json-schema/attributes/formats/ip6.rb +0 -20
  77. data/lib/json-schema/attributes/maximum.rb +0 -17
  78. data/lib/json-schema/attributes/maximum_inclusive.rb +0 -17
  79. data/lib/json-schema/attributes/maxitems.rb +0 -14
  80. data/lib/json-schema/attributes/maxlength.rb +0 -16
  81. data/lib/json-schema/attributes/maxproperties.rb +0 -14
  82. data/lib/json-schema/attributes/minimum.rb +0 -17
  83. data/lib/json-schema/attributes/minimum_inclusive.rb +0 -17
  84. data/lib/json-schema/attributes/minitems.rb +0 -14
  85. data/lib/json-schema/attributes/minlength.rb +0 -16
  86. data/lib/json-schema/attributes/minproperties.rb +0 -14
  87. data/lib/json-schema/attributes/properties_v4.rb +0 -58
  88. data/lib/json-schema/uri/file.rb +0 -36
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTc1NDAxODkxMmNiYTQ4YzdiMzNkMWEyYjlhYTQ5MTU5MWExMTFhZQ==
5
- data.tar.gz: !binary |-
6
- ZmQxNjIyOTU5ZGQyZGQ5ZDIxYmYxMGQwMGIzYjliMDMyYjQ5Y2EwMA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YjVlZjkzNWE5YTA3MjhlNTY0ZmMyMGRiNGE0YzYwODE1N2I3ZTFhMTAzYjQ1
10
- NTJjZGU2ZTE1OTg3NDJjNThhYzAwMGRiYzZiMzIzZWJiODRmNzA5NjVjMzAw
11
- ZTE4MjdjYzE3NGQ0ZjlhYmQ3NWViZjVmOWNhYzc2YjY2NWNlYTU=
12
- data.tar.gz: !binary |-
13
- ODA4M2U2YTkyMmM1NjhlMTUyN2M3NjJiODI3ZmUzMzNhYTFkNTE1YmRkYWM4
14
- MWNiODZlYmQ3YjdkY2M4ZDk3ZDVkNTZlYmJkNmNjNWVjODhjOWQxNzA5MmU2
15
- YjQwMDBmMjZmODdkOTI5YjBjMzUxMGJiOWNjY2JmNzZlZWZhYjY=
2
+ SHA1:
3
+ metadata.gz: b4d20081a44ab34c2a1d12268a7e4160b4070221
4
+ data.tar.gz: a9b98f1d541ad64563095ee77d03738e3d6fbfaa
5
+ SHA512:
6
+ metadata.gz: 433b1267a8f4902cf007e6407fbd9bc253cd5884ae9c1311825cdf1e019c784239c2e7189e11e8d752449c27a5f74f22c00dbb6205ae3ae3d5342874628584a4
7
+ data.tar.gz: 57f5da1f4a399df4c9025d6955a6d554fc41c23ac009651501f7badb5c622db272a53bbd3d3a2cac849b34055cbbb89d5c99775968e1b69ff8ddc3933dfc8966
@@ -1,17 +1,18 @@
1
- !https://travis-ci.org/hoxworth/json-schema.svg?branch=master!:https://travis-ci.org/hoxworth/json-schema
2
- !https://codeclimate.com/github/hoxworth/json-schema/badges/gpa.svg!:https://codeclimate.com/github/hoxworth/json-schema
1
+ !https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master!:https://travis-ci.org/ruby-json-schema/json-schema
2
+ !https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg!:https://codeclimate.com/github/ruby-json-schema/json-schema
3
3
 
4
4
  h1. Ruby JSON Schema Validator
5
5
 
6
6
  This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04. Legacy support for "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03, "JSON Schema Draft 2":http://tools.ietf.org/html/draft-zyp-json-schema-02, and "JSON Schema Draft 1":http://tools.ietf.org/html/draft-zyp-json-schema-01 is also included.
7
7
 
8
- h2. Version 2.0.0 Upgrade Notes
8
+ h2. Additional Resources
9
9
 
10
- Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the <code>$schema</code> keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade.
10
+ * "Google Groups":https://groups.google.com/forum/#!forum/ruby-json-schema
11
+ * #ruby-json-schema on chat.freenode.net
11
12
 
12
- h2. Dependencies
13
+ h2. Version 2.0.0 Upgrade Notes
13
14
 
14
- The JSON::Schema library has no dependencies if the validation methods are called using Ruby objects. However, either the <code>json</code> or the <code>yajl-ruby</code> gem needs to be installed to validate JSON strings or files containing JSON data.
15
+ Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the <code>$schema</code> keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade.
15
16
 
16
17
  h2. Installation
17
18
 
@@ -277,6 +278,32 @@ data = {
277
278
  JSON::Validator.validate(schema, data, :version => :draft2)
278
279
  </pre>
279
280
 
281
+ h3. Explicitly specifying the type of the data
282
+
283
+ By default, json-schema accepts a variety of different types for the data parameter, and it will try to work out what to do with it dynamically. You can pass it a string uri (in which case it will download the json from that location before validating), a string of JSON text, or simply a ruby object (such as an array or hash representing parsed json). However, sometimes the nature of the data is ambiguous (for example, is "http://github.com" just a string, or is it a uri?). In other situations, you have already parsed your JSON, and you don't need to re-parse it.
284
+
285
+ If you want to be explict about what kind of data is being parsed, JSON schema supports a number of options:
286
+
287
+ <pre>
288
+ require 'rubygems'
289
+ require 'json-schema'
290
+
291
+ schema = {
292
+ "type" => "string"
293
+ }
294
+
295
+ # examines the data, determines it's a uri, then tries to load data from it
296
+ JSON::Validator.validate(schema, 'https://api.github.com') # returns false
297
+
298
+ # data is already parsed json - just accept it as-is
299
+ JSON::Validator.validate(schema, 'https://api.github.com', :parse_data => false) # returns true
300
+
301
+ # data is parsed to a json string
302
+ JSON::Validator.validate(schema, '"https://api.github.com"', :json => true) # returns true
303
+
304
+ # loads data from the uri
305
+ JSON::Validator.validate(schema, 'https://api.github.com', :uri => true) # returns false
306
+ </pre>
280
307
 
281
308
  h3. Extend an existing schema and validate against it
282
309
 
@@ -332,7 +359,7 @@ JSON::Validator.validate(schema,data) # => false
332
359
 
333
360
  h3. Custom format validation
334
361
 
335
- The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a <code>JSON::Schema::CustomFormatError</code> to indicate a format violation. The error message will be prepended by the property namne, e.g. "The property '#a'":
362
+ The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a <code>JSON::Schema::CustomFormatError</code> to indicate a format violation. The error message will be prepended by the property name, e.g. "The property '#a'":
336
363
 
337
364
  <pre>
338
365
  require 'rubygems'
@@ -370,6 +397,30 @@ errors = JSON::Validator.fully_validate(schema, {"a" => "23"})
370
397
 
371
398
  </pre>
372
399
 
400
+ h2. Controlling Remote Schema Reading
401
+
402
+ In some cases, you may wish to prevent the JSON Schema library from making HTTP calls or reading local files in order to resolve <code>$ref</code> schemas. If you fully control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance:
403
+
404
+ <pre>
405
+ schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema'))
406
+ JSON::Validator.add_schema(schema)
407
+ </pre>
408
+
409
+ If more extensive control is necessary, the <code>JSON::Schema::Reader</code> instance used can be configured in a few ways:
410
+
411
+ <pre>
412
+ # Change the default schema reader used
413
+ JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)
414
+
415
+ # For this validation call, use a reader which only accepts URIs from my-website.com
416
+ schema_reader = JSON::Schema::Reader.new(
417
+ :accept_uri => proc { |uri| uri.host == 'my-website.com' }
418
+ )
419
+ JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader)
420
+ </pre>
421
+
422
+ The <code>JSON::Schema::Reader</code> interface requires only an object which responds to <code>read(string)</code> and returns a <code>JSON::Schema</code> instance. See the "API documentation":http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader for more information.
423
+
373
424
  h2. JSON Backends
374
425
 
375
426
  The JSON Schema library currently supports the <code>json</code> and <code>yajl-ruby</code> backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user.
@@ -9,9 +9,11 @@ if Gem::Specification::find_all_by_name('multi_json').any?
9
9
  end
10
10
 
11
11
  require 'json-schema/util/array_set'
12
+ require 'json-schema/util/uri'
12
13
  require 'json-schema/schema'
14
+ require 'json-schema/schema/reader'
13
15
  require 'json-schema/validator'
16
+
14
17
  Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/*.rb")].each {|file| require file }
15
18
  Dir[File.join(File.dirname(__FILE__), "json-schema/attributes/formats/*.rb")].each {|file| require file }
16
19
  Dir[File.join(File.dirname(__FILE__), "json-schema/validators/*.rb")].sort!.each {|file| require file }
17
- require 'json-schema/uri/file'
@@ -4,19 +4,22 @@ module JSON
4
4
  class Schema
5
5
  class AdditionalItemsAttribute < Attribute
6
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if data.is_a?(Array) && current_schema.schema['items'].is_a?(Array)
8
- if current_schema.schema['additionalItems'] == false && current_schema.schema['items'].length != data.length
7
+ return unless data.is_a?(Array)
8
+
9
+ schema = current_schema.schema
10
+ return unless schema['items'].is_a?(Array)
11
+
12
+ case schema['additionalItems']
13
+ when false
14
+ if schema['items'].length != data.length
9
15
  message = "The property '#{build_fragment(fragments)}' contains additional array elements outside of the schema when none are allowed"
10
16
  validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
11
- elsif current_schema.schema['additionalItems'].is_a?(Hash)
12
- schema = JSON::Schema.new(current_schema.schema['additionalItems'],current_schema.uri,validator)
13
- data.each_with_index do |item,i|
14
- if i >= current_schema.schema['items'].length
15
- fragments << i.to_s
16
- schema.validate(item, fragments, processor, options)
17
- fragments.pop
18
- end
19
- end
17
+ end
18
+ when Hash
19
+ additional_items_schema = JSON::Schema.new(schema['additionalItems'], current_schema.uri, validator)
20
+ data.each_with_index do |item, i|
21
+ next if i < schema['items'].length
22
+ additional_items_schema.validate(item, fragments + [i.to_s], processor, options)
20
23
  end
21
24
  end
22
25
  end
@@ -5,62 +5,52 @@ module JSON
5
5
  class Schema
6
6
  class AdditionalPropertiesAttribute < Attribute
7
7
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
8
- if data.is_a?(Hash) && (
9
- current_schema.schema['type'].nil? || (
10
- current_schema.schema['type'].is_a?(String) &&
11
- current_schema.schema['type'].downcase == 'object'
12
- )
13
- )
14
- extra_properties = data.keys
15
- extra_properties = remove_valid_properties(extra_properties, current_schema, validator)
8
+ schema = current_schema.schema
9
+ return unless data.is_a?(Hash) && (schema['type'].nil? || schema['type'] == 'object')
16
10
 
17
- addprop = current_schema.schema['additionalProperties']
18
- if addprop.is_a?(Hash)
19
- matching_properties = extra_properties # & addprop.keys
20
- matching_properties.each do |key|
21
- schema = JSON::Schema.new(addprop[key] || addprop, current_schema.uri, validator)
22
- fragments << key
23
- schema.validate(data[key],fragments,processor,options)
24
- fragments.pop
25
- end
26
- extra_properties -= matching_properties
27
- end
28
- if !extra_properties.empty? and (addprop == false or (addprop.is_a?(Hash) and !addprop.empty?))
29
- message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
30
- validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
11
+ extra_properties = remove_valid_properties(data.keys, current_schema, validator)
12
+
13
+ addprop = schema['additionalProperties']
14
+ if addprop.is_a?(Hash)
15
+ matching_properties = extra_properties # & addprop.keys
16
+ matching_properties.each do |key|
17
+ additional_property_schema = JSON::Schema.new(addprop[key] || addprop, current_schema.uri, validator)
18
+ additional_property_schema.validate(data[key], fragments + [key], processor, options)
31
19
  end
20
+ extra_properties -= matching_properties
21
+ end
22
+
23
+ if extra_properties.any? && (addprop == false || (addprop.is_a?(Hash) && !addprop.empty?))
24
+ message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
25
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
32
26
  end
33
27
  end
34
28
 
35
29
  def self.remove_valid_properties(extra_properties, current_schema, validator)
30
+ schema = current_schema.schema
36
31
 
37
- if current_schema.schema['properties']
38
- extra_properties = extra_properties - current_schema.schema['properties'].keys
39
- end
32
+ if schema['properties']
33
+ extra_properties = extra_properties - schema['properties'].keys
34
+ end
40
35
 
41
- if current_schema.schema['patternProperties']
42
- current_schema.schema['patternProperties'].each_key do |key|
43
- r = Regexp.new(key)
44
- extras_clone = extra_properties.clone
45
- extras_clone.each do |prop|
46
- if r.match(prop)
47
- extra_properties = extra_properties - [prop]
48
- end
49
- end
50
- end
36
+ if schema['patternProperties']
37
+ schema['patternProperties'].each_key do |key|
38
+ regexp = Regexp.new(key)
39
+ extra_properties.reject! { |prop| regexp.match(prop) }
51
40
  end
41
+ end
52
42
 
53
- if schemas= current_schema.schema['extends']
54
- schemas = [schemas] if !schemas.is_a?(Array)
55
- schemas.each do |schema_value|
56
- temp_uri,extended_schema= JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator)
57
- if extended_schema
58
- extra_properties= remove_valid_properties(extra_properties, extended_schema, validator)
59
- end
43
+ if extended_schemas = schema['extends']
44
+ extended_schemas = [extended_schemas] unless extended_schemas.is_a?(Array)
45
+ extended_schemas.each do |schema_value|
46
+ _, extended_schema = JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator)
47
+ if extended_schema
48
+ extra_properties = remove_valid_properties(extra_properties, extended_schema, validator)
60
49
  end
61
50
  end
51
+ end
62
52
 
63
- extra_properties
53
+ extra_properties
64
54
  end
65
55
 
66
56
  end
@@ -8,6 +8,8 @@ module JSON
8
8
  errors = Hash.new { |hsh, k| hsh[k] = [] }
9
9
  valid = false
10
10
 
11
+ original_data = data.is_a?(Hash) ? data.clone : data
12
+
11
13
  current_schema.schema['anyOf'].each_with_index do |element, schema_index|
12
14
  schema = JSON::Schema.new(element,current_schema.uri,validator)
13
15
 
@@ -30,6 +32,8 @@ module JSON
30
32
  end
31
33
 
32
34
  break if valid
35
+
36
+ data = original_data
33
37
  end
34
38
 
35
39
  if !valid
@@ -4,29 +4,41 @@ module JSON
4
4
  class Schema
5
5
  class DependenciesAttribute < Attribute
6
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if data.is_a?(Hash)
8
- current_schema.schema['dependencies'].each do |property,dependency_value|
9
- if data.has_key?(property.to_s)
10
- if dependency_value.is_a?(String)
11
- if !data.has_key?(dependency_value.to_s)
12
- message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{dependency_value}'"
13
- validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
14
- end
15
- elsif dependency_value.is_a?(Array)
16
- dependency_value.each do |value|
17
- if !data.has_key?(value.to_s)
18
- message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'"
19
- validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
20
- end
21
- end
22
- else
23
- schema = JSON::Schema.new(dependency_value,current_schema.uri,validator)
24
- schema.validate(data, fragments, processor, options)
25
- end
7
+ return unless data.is_a?(Hash)
8
+
9
+ current_schema.schema['dependencies'].each do |property, dependency_value|
10
+ next unless data.has_key?(property.to_s)
11
+ next unless accept_value?(dependency_value)
12
+
13
+ case dependency_value
14
+ when String
15
+ validate_dependency(current_schema, data, property, dependency_value, fragments, processor, self, options)
16
+ when Array
17
+ dependency_value.each do |value|
18
+ validate_dependency(current_schema, data, property, value, fragments, processor, self, options)
26
19
  end
20
+ else
21
+ schema = JSON::Schema.new(dependency_value, current_schema.uri, validator)
22
+ schema.validate(data, fragments, processor, options)
27
23
  end
28
24
  end
29
25
  end
26
+
27
+ def self.validate_dependency(schema, data, property, value, fragments, processor, attribute, options)
28
+ return if data.key?(value.to_s)
29
+ message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'"
30
+ validation_error(processor, message, fragments, schema, attribute, options[:record_errors])
31
+ end
32
+
33
+ def self.accept_value?(value)
34
+ value.is_a?(String) || value.is_a?(Array) || value.is_a?(Hash)
35
+ end
36
+ end
37
+
38
+ class DependenciesV4Attribute < DependenciesAttribute
39
+ def self.accept_value?(value)
40
+ value.is_a?(Array) || value.is_a?(Hash)
41
+ end
30
42
  end
31
43
  end
32
44
  end
@@ -4,9 +4,8 @@ module JSON
4
4
  class Schema
5
5
  class DisallowAttribute < Attribute
6
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if validator.attributes['type']
8
- validator.attributes['type'].validate(current_schema, data, fragments, processor, validator, {:disallow => true}.merge(options))
9
- end
7
+ return unless type = validator.attributes['type']
8
+ type.validate(current_schema, data, fragments, processor, validator, options.merge(:disallow => true))
10
9
  end
11
10
  end
12
11
  end
@@ -3,14 +3,18 @@ require 'json-schema/attribute'
3
3
  module JSON
4
4
  class Schema
5
5
  class DivisibleByAttribute < Attribute
6
+ def self.keyword
7
+ 'divisibleBy'
8
+ end
9
+
6
10
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if data.is_a?(Numeric)
8
- if current_schema.schema['divisibleBy'] == 0 ||
9
- current_schema.schema['divisibleBy'] == 0.0 ||
10
- (BigDecimal.new(data.to_s) % BigDecimal.new(current_schema.schema['divisibleBy'].to_s)).to_f != 0
11
- message = "The property '#{build_fragment(fragments)}' was not divisible by #{current_schema.schema['divisibleBy']}"
12
- validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
13
- end
11
+ return unless data.is_a?(Numeric)
12
+
13
+ factor = current_schema.schema[keyword]
14
+
15
+ if factor == 0 || factor == 0.0 || (BigDecimal.new(data.to_s) % BigDecimal.new(factor.to_s)).to_f != 0
16
+ message = "The property '#{build_fragment(fragments)}' was not divisible by #{factor}"
17
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
14
18
  end
15
19
  end
16
20
  end
@@ -4,22 +4,20 @@ module JSON
4
4
  class Schema
5
5
  class EnumAttribute < Attribute
6
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if !current_schema.schema['enum'].include?(data)
8
- message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match one of the following values:"
9
- current_schema.schema['enum'].each {|val|
10
- if val.is_a?(NilClass)
11
- message += " null,"
12
- elsif val.is_a?(Array)
13
- message += " (array),"
14
- elsif val.is_a?(Hash)
15
- message += " (object),"
16
- else
17
- message += " #{val.to_s},"
18
- end
19
- }
20
- message.chop!
21
- validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
22
- end
7
+ enum = current_schema.schema['enum']
8
+ return if enum.include?(data)
9
+
10
+ values = enum.map { |val|
11
+ case val
12
+ when nil then 'null'
13
+ when Array then 'array'
14
+ when Hash then 'object'
15
+ else val.to_s
16
+ end
17
+ }.join(', ')
18
+
19
+ message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match one of the following values: #{values}"
20
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
23
21
  end
24
22
  end
25
23
  end
@@ -1,16 +1,13 @@
1
1
  require 'json-schema/attribute'
2
- require 'uri'
3
2
 
4
3
  module JSON
5
4
  class Schema
6
5
  class FormatAttribute < Attribute
7
-
8
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
9
- if self.data_valid_for_type?(data, current_schema.schema['type'])
10
- format = current_schema.schema['format'].to_s
11
- validator = validator.formats[format]
12
- validator.validate(current_schema, data, fragments, processor, validator, options) unless validator.nil?
13
- end
7
+ return unless data_valid_for_type?(data, current_schema.schema['type'])
8
+ format = current_schema.schema['format'].to_s
9
+ validator = validator.formats[format]
10
+ validator.validate(current_schema, data, fragments, processor, validator, options) unless validator.nil?
14
11
  end
15
12
  end
16
13
  end
@@ -4,14 +4,11 @@ module JSON
4
4
  class Schema
5
5
  class DateTimeV4Format < FormatAttribute
6
6
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
- if data.is_a?(String)
8
- error_message = "The property '#{build_fragment(fragments)}' must be a valid RFC3339 date/time string"
9
- begin
10
- DateTime.rfc3339(data)
11
- rescue ArgumentError
12
- validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
13
- end
14
- end
7
+ return unless data.is_a?(String)
8
+ DateTime.rfc3339(data)
9
+ rescue ArgumentError
10
+ error_message = "The property '#{build_fragment(fragments)}' must be a valid RFC3339 date/time string"
11
+ validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
15
12
  end
16
13
  end
17
14
  end