json-schema 2.8.1 → 4.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 +4 -4
- data/README.md +54 -10
- 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 -0
- data/lib/json-schema/attributes/disallow.rb +2 -1
- data/lib/json-schema/attributes/enum.rb +2 -2
- data/lib/json-schema/attributes/extends.rb +6 -6
- data/lib/json-schema/attributes/format.rb +2 -1
- data/lib/json-schema/attributes/formats/date.rb +1 -0
- data/lib/json-schema/attributes/formats/date_time.rb +2 -1
- data/lib/json-schema/attributes/formats/date_time_v4.rb +1 -0
- data/lib/json-schema/attributes/formats/ip.rb +1 -1
- data/lib/json-schema/attributes/formats/uri.rb +1 -0
- data/lib/json-schema/attributes/items.rb +1 -0
- data/lib/json-schema/attributes/limits/numeric.rb +1 -1
- 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 +1 -0
- data/lib/json-schema/attributes/properties.rb +7 -7
- data/lib/json-schema/attributes/properties_v4.rb +1 -1
- data/lib/json-schema/attributes/propertynames.rb +23 -0
- data/lib/json-schema/attributes/ref.rb +7 -7
- data/lib/json-schema/attributes/required.rb +3 -2
- 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 +4 -5
- 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 +7 -7
- data/lib/json-schema/util/uuid.rb +227 -226
- data/lib/json-schema/validator.rb +119 -114
- 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 -2
- data/resources/draft-06.json +12 -12
- metadata +15 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b6a5072f20570ae4262df13648a1b637b5db2c02cf881c2728277ea5a203f6d
|
4
|
+
data.tar.gz: 4b92633224b1338d58918e7a2d2f5d3e117fee03409455d6f47ea51c8bef7b18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b5301a03a3fb7d3a43c275858df22d41cface2a465ff2fcfda28c9528f491e6a8f302fbbf52232de68e31d6a32540b9ad8a392fab82ec2b2113980e83119b72
|
7
|
+
data.tar.gz: 16f57a870e6b75280f5376d57785ad94500cbfd50bc3ea9ba01df486d0938c36907114780bacfc4860359e73d7adf87ce5c73205ef52ebea1f829b64d7630906
|
data/README.md
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
|
2
|
-
[](https://travis-ci.org/ruby-json-schema/json-schema)
|
3
|
-
[](https://codeclimate.com/github/ruby-json-schema/json-schema)
|
1
|
+
# Ruby JSON Schema Validator
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
[](https://github.com/voxpupuli/json-schema/blob/master/LICENSE)
|
4
|
+
[](https://github.com/voxpupuli/json-schema/actions/workflows/test.yml)
|
5
|
+
[](https://github.com/voxpupuli/json-schema/actions/workflows/release.yml)
|
6
|
+
[](https://rubygems.org/gems/json-schema)
|
7
|
+
[](https://rubygems.org/gems/json-schema)
|
8
|
+
[](#transfer-notice)
|
7
9
|
|
8
10
|
This library is intended to provide Ruby with an interface for validating JSON
|
9
11
|
objects against a JSON schema conforming to [JSON Schema Draft
|
10
|
-
|
12
|
+
6](https://tools.ietf.org/html/draft-wright-json-schema-01). Legacy support for
|
13
|
+
[JSON Schema Draft 4](http://tools.ietf.org/html/draft-zyp-json-schema-04),
|
11
14
|
[JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03),
|
12
15
|
[JSON Schema Draft 2](http://tools.ietf.org/html/draft-zyp-json-schema-02), and
|
13
16
|
[JSON Schema Draft 1](http://tools.ietf.org/html/draft-zyp-json-schema-01) is
|
@@ -17,7 +20,7 @@ Additional Resources
|
|
17
20
|
--------------------
|
18
21
|
|
19
22
|
- [Google Groups](https://groups.google.com/forum/#!forum/ruby-json-schema)
|
20
|
-
- #
|
23
|
+
- #voxpupuli on irc.libera.chat
|
21
24
|
|
22
25
|
Version 2.0.0 Upgrade Notes
|
23
26
|
---------------------------
|
@@ -27,6 +30,14 @@ default**, so schemas that do not declare a validator using the `$schema`
|
|
27
30
|
keyword will use Draft-04 now instead of Draft-03. This is the reason for the
|
28
31
|
major version upgrade.
|
29
32
|
|
33
|
+
Version 3.0.0 Upgrade Notes
|
34
|
+
---------------------------
|
35
|
+
|
36
|
+
All individual changes are documented in the CHANGELOG.md. The biggest change
|
37
|
+
is that the new version only supports Ruby 2.5 and newer. Take a look into the
|
38
|
+
gemspec file to see the currently supported Ruby version and also
|
39
|
+
`.github/workflows/test.yml` to see the Ruby versions we test on.
|
40
|
+
|
30
41
|
Installation
|
31
42
|
------------
|
32
43
|
|
@@ -39,8 +50,8 @@ gem install json-schema
|
|
39
50
|
From the git repo:
|
40
51
|
|
41
52
|
```sh
|
42
|
-
|
43
|
-
|
53
|
+
gem build json-schema.gemspec
|
54
|
+
gem install json-schema-*.gem
|
44
55
|
```
|
45
56
|
|
46
57
|
Validation
|
@@ -166,7 +177,7 @@ JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}])
|
|
166
177
|
JSON::Validator.fully_validate(schema, { "a" => "taco" }, :errors_as_objects => true)
|
167
178
|
|
168
179
|
#
|
169
|
-
# with the `:strict` option, all properties are
|
180
|
+
# with the `:strict` option, all properties are considered to have `"required": true` and all objects `"additionalProperties": false`
|
170
181
|
#
|
171
182
|
|
172
183
|
# => true
|
@@ -230,6 +241,19 @@ JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false)
|
|
230
241
|
# => false
|
231
242
|
JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false)
|
232
243
|
|
244
|
+
#
|
245
|
+
# with the `:parse_integer` option set to false, the integer value given as string will not be parsed.
|
246
|
+
#
|
247
|
+
|
248
|
+
# => true
|
249
|
+
JSON::Validator.validate({type: "integer"}, "23")
|
250
|
+
# => false
|
251
|
+
JSON::Validator.validate({type: "integer"}, "23", parse_integer: false)
|
252
|
+
# => true
|
253
|
+
JSON::Validator.validate({type: "string"}, "123", parse_integer: false)
|
254
|
+
# => false
|
255
|
+
JSON::Validator.validate({type: "string"}, "123")
|
256
|
+
|
233
257
|
#
|
234
258
|
# with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path)
|
235
259
|
#
|
@@ -472,3 +496,23 @@ value is of the correct datatype (e.g., an instance value is validated to be an
|
|
472
496
|
integer or a float in the case of 'utc-millisec').
|
473
497
|
|
474
498
|
Additionally, JSON::Validator does not handle any json hyperschema attributes.
|
499
|
+
|
500
|
+
# Transfer Notice
|
501
|
+
|
502
|
+
This plugin was originally authored by [Iain Beeston](https://github.com/iainbeeston).
|
503
|
+
The maintainer preferred that [Vox Pupuli](https://voxpupuli.org/) take ownership of the module for future improvement and maintenance.
|
504
|
+
Existing pull requests and issues were transferred, please fork and continue to contribute [here](https://github.com/voxpupuli/json-schema).
|
505
|
+
|
506
|
+
# License
|
507
|
+
|
508
|
+
This gem is licensed unter the [MIT license](LICENSE.md).
|
509
|
+
|
510
|
+
## Release information
|
511
|
+
|
512
|
+
To make a new release, please do:
|
513
|
+
* update the version in VERSION.yml
|
514
|
+
* Install gems with `bundle install --with release --path .vendor`
|
515
|
+
* generate the changelog with `bundle exec rake changelog`
|
516
|
+
* Check if the new version matches the closed issues/PRs in the changelog
|
517
|
+
* Create a PR with it
|
518
|
+
* After it got merged, push a tag. GitHub actions will do the actual release to rubygems and GitHub Packages
|
@@ -3,8 +3,7 @@ require 'json-schema/errors/validation_error'
|
|
3
3
|
module JSON
|
4
4
|
class Schema
|
5
5
|
class Attribute
|
6
|
-
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
-
end
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {}); end
|
8
7
|
|
9
8
|
def self.build_fragment(fragments)
|
10
9
|
"#/#{fragments.join('/')}"
|
@@ -24,14 +23,14 @@ module JSON
|
|
24
23
|
end
|
25
24
|
|
26
25
|
TYPE_CLASS_MAPPINGS = {
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
'string' => String,
|
27
|
+
'number' => Numeric,
|
28
|
+
'integer' => Integer,
|
29
|
+
'boolean' => [TrueClass, FalseClass],
|
30
|
+
'object' => Hash,
|
31
|
+
'array' => Array,
|
32
|
+
'null' => NilClass,
|
33
|
+
'any' => Object,
|
35
34
|
}
|
36
35
|
|
37
36
|
def self.data_valid_for_type?(data, type)
|
@@ -41,11 +40,11 @@ module JSON
|
|
41
40
|
|
42
41
|
# Lookup Schema type of given class instance
|
43
42
|
def self.type_of_data(data)
|
44
|
-
type,
|
43
|
+
type, = TYPE_CLASS_MAPPINGS.map { |k, v| [k, v] }.sort_by do |(_, v)|
|
45
44
|
-Array(v).map { |klass| klass.ancestors.size }.max
|
46
|
-
|
47
|
-
Array(v).any? { |klass| data.
|
48
|
-
|
45
|
+
end.find do |(_, v)|
|
46
|
+
Array(v).any? { |klass| data.is_a?(klass) }
|
47
|
+
end
|
49
48
|
type
|
50
49
|
end
|
51
50
|
end
|
@@ -19,6 +19,7 @@ module JSON
|
|
19
19
|
additional_items_schema = JSON::Schema.new(schema['additionalItems'], current_schema.uri, validator)
|
20
20
|
data.each_with_index do |item, i|
|
21
21
|
next if i < schema['items'].length
|
22
|
+
|
22
23
|
additional_items_schema.validate(item, fragments + [i.to_s], processor, options)
|
23
24
|
end
|
24
25
|
end
|
@@ -33,11 +33,9 @@ module JSON
|
|
33
33
|
extra_properties = extra_properties - schema['properties'].keys
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
extra_properties.reject! { |prop| regexp.match(prop) }
|
40
|
-
end
|
36
|
+
schema['patternProperties']&.each_key do |key|
|
37
|
+
regexp = Regexp.new(key)
|
38
|
+
extra_properties.reject! { |prop| regexp.match(prop) }
|
41
39
|
end
|
42
40
|
|
43
41
|
if extended_schemas = schema['extends']
|
@@ -52,7 +50,6 @@ module JSON
|
|
52
50
|
|
53
51
|
extra_properties
|
54
52
|
end
|
55
|
-
|
56
53
|
end
|
57
54
|
end
|
58
55
|
end
|
@@ -7,18 +7,20 @@ module JSON
|
|
7
7
|
# Create an hash to hold errors that are generated during validation
|
8
8
|
errors = Hash.new { |hsh, k| hsh[k] = [] }
|
9
9
|
valid = true
|
10
|
+
message = nil
|
10
11
|
|
11
12
|
current_schema.schema['allOf'].each_with_index do |element, schema_index|
|
12
|
-
schema = JSON::Schema.new(element,current_schema.uri,validator)
|
13
|
+
schema = JSON::Schema.new(element, current_schema.uri, validator)
|
13
14
|
|
14
15
|
# We're going to add a little cruft here to try and maintain any validation errors that occur in the allOf
|
15
16
|
# We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto an error array
|
16
17
|
pre_validation_error_count = validation_errors(processor).count
|
17
18
|
|
18
19
|
begin
|
19
|
-
schema.validate(data,fragments,processor,options)
|
20
|
-
rescue ValidationError
|
20
|
+
schema.validate(data, fragments, processor, options)
|
21
|
+
rescue ValidationError => e
|
21
22
|
valid = false
|
23
|
+
message = e.message
|
22
24
|
end
|
23
25
|
|
24
26
|
diff = validation_errors(processor).count - pre_validation_error_count
|
@@ -29,7 +31,7 @@ module JSON
|
|
29
31
|
end
|
30
32
|
|
31
33
|
if !valid || !errors.empty?
|
32
|
-
message
|
34
|
+
message ||= "The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match all of the required schemas"
|
33
35
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
34
36
|
validation_errors(processor).last.sub_errors = errors
|
35
37
|
end
|
@@ -11,14 +11,14 @@ module JSON
|
|
11
11
|
original_data = data.is_a?(Hash) ? data.clone : data
|
12
12
|
|
13
13
|
current_schema.schema['anyOf'].each_with_index do |element, schema_index|
|
14
|
-
schema = JSON::Schema.new(element,current_schema.uri,validator)
|
14
|
+
schema = JSON::Schema.new(element, current_schema.uri, validator)
|
15
15
|
|
16
16
|
# We're going to add a little cruft here to try and maintain any validation errors that occur in the anyOf
|
17
17
|
# We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto a union error
|
18
18
|
pre_validation_error_count = validation_errors(processor).count
|
19
19
|
|
20
20
|
begin
|
21
|
-
schema.validate(data,fragments,processor,options)
|
21
|
+
schema.validate(data, fragments, processor, options)
|
22
22
|
valid = true
|
23
23
|
rescue ValidationError
|
24
24
|
# We don't care that these schemas don't validate - we only care that one validated
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class ConstAttribute < Attribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
const_value = current_schema.schema['const']
|
8
|
+
unless const_value == data
|
9
|
+
message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match constant '#{const_value}'"
|
10
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -26,6 +26,7 @@ module JSON
|
|
26
26
|
|
27
27
|
def self.validate_dependency(schema, data, property, value, fragments, processor, attribute, options)
|
28
28
|
return if data.key?(value.to_s)
|
29
|
+
|
29
30
|
message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'"
|
30
31
|
validation_error(processor, message, fragments, schema, attribute, options[:record_errors])
|
31
32
|
end
|
@@ -5,7 +5,8 @@ module JSON
|
|
5
5
|
class DisallowAttribute < Attribute
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
7
|
return unless type = validator.attributes['type']
|
8
|
-
|
8
|
+
|
9
|
+
type.validate(current_schema, data, fragments, processor, validator, options.merge(disallow: true))
|
9
10
|
end
|
10
11
|
end
|
11
12
|
end
|
@@ -7,14 +7,14 @@ module JSON
|
|
7
7
|
enum = current_schema.schema['enum']
|
8
8
|
return if enum.include?(data)
|
9
9
|
|
10
|
-
values = enum.map
|
10
|
+
values = enum.map do |val|
|
11
11
|
case val
|
12
12
|
when nil then 'null'
|
13
13
|
when Array then 'array'
|
14
14
|
when Hash then 'object'
|
15
15
|
else val.to_s
|
16
16
|
end
|
17
|
-
|
17
|
+
end.join(', ')
|
18
18
|
|
19
19
|
message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match one of the following values: #{values}"
|
20
20
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
@@ -8,7 +8,7 @@ module JSON
|
|
8
8
|
schemas = current_schema.schema['extends']
|
9
9
|
schemas = [schemas] if !schemas.is_a?(Array)
|
10
10
|
schemas.each do |s|
|
11
|
-
uri,schema = get_extended_uri_and_schema(s, current_schema, validator)
|
11
|
+
uri, schema = get_extended_uri_and_schema(s, current_schema, validator)
|
12
12
|
if schema
|
13
13
|
schema.validate(data, fragments, processor, options)
|
14
14
|
elsif uri
|
@@ -22,15 +22,15 @@ module JSON
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.get_extended_uri_and_schema(s, current_schema, validator)
|
25
|
-
uri,schema = nil,nil
|
25
|
+
uri, schema = nil, nil
|
26
26
|
|
27
27
|
if s.is_a?(Hash)
|
28
28
|
uri = current_schema.uri
|
29
29
|
if s['$ref']
|
30
|
-
ref_uri,ref_schema = JSON::Schema::RefAttribute.get_referenced_uri_and_schema(s, current_schema, validator)
|
30
|
+
ref_uri, ref_schema = JSON::Schema::RefAttribute.get_referenced_uri_and_schema(s, current_schema, validator)
|
31
31
|
if ref_schema
|
32
32
|
if s.size == 1 # Check if anything else apart from $ref
|
33
|
-
uri,schema = ref_uri,ref_schema
|
33
|
+
uri, schema = ref_uri, ref_schema
|
34
34
|
else
|
35
35
|
s = s.dup
|
36
36
|
s.delete '$ref'
|
@@ -38,10 +38,10 @@ module JSON
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
-
schema ||= JSON::Schema.new(s,uri,validator)
|
41
|
+
schema ||= JSON::Schema.new(s, uri, validator)
|
42
42
|
end
|
43
43
|
|
44
|
-
[uri,schema]
|
44
|
+
[uri, schema]
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -5,9 +5,10 @@ module JSON
|
|
5
5
|
class FormatAttribute < Attribute
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
7
|
return unless data_valid_for_type?(data, current_schema.schema['type'])
|
8
|
+
|
8
9
|
format = current_schema.schema['format'].to_s
|
9
10
|
validator = validator.formats[format]
|
10
|
-
validator
|
11
|
+
validator&.validate(current_schema, data, fragments, processor, validator, options)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -10,12 +10,13 @@ module JSON
|
|
10
10
|
if data.is_a?(String)
|
11
11
|
error_message = "The property '#{build_fragment(fragments)}' must be a date/time in the ISO-8601 format of YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss.ssZ"
|
12
12
|
if (m = REGEXP.match(data))
|
13
|
-
parts = data.split(
|
13
|
+
parts = data.split('T')
|
14
14
|
|
15
15
|
begin
|
16
16
|
Date.parse(parts[0])
|
17
17
|
rescue ArgumentError => e
|
18
18
|
raise e unless e.message == 'invalid date'
|
19
|
+
|
19
20
|
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
20
21
|
return
|
21
22
|
end
|
@@ -5,6 +5,7 @@ module JSON
|
|
5
5
|
class DateTimeV4Format < FormatAttribute
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
7
|
return unless data.is_a?(String)
|
8
|
+
|
8
9
|
DateTime.rfc3339(data)
|
9
10
|
rescue ArgumentError
|
10
11
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid RFC3339 date/time string"
|
@@ -6,6 +6,7 @@ module JSON
|
|
6
6
|
class UriFormat < FormatAttribute
|
7
7
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
8
8
|
return unless data.is_a?(String)
|
9
|
+
|
9
10
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid URI"
|
10
11
|
begin
|
11
12
|
JSON::Util::URI.parse(data)
|
@@ -9,7 +9,7 @@ module JSON
|
|
9
9
|
|
10
10
|
def self.error_message(schema)
|
11
11
|
exclusivity = exclusive?(schema) ? 'exclusively' : 'inclusively'
|
12
|
-
format(
|
12
|
+
format('did not have a %s value of %s, %s', limit_name, limit(schema), exclusivity)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -7,7 +7,7 @@ module JSON
|
|
7
7
|
return unless data.is_a?(Numeric)
|
8
8
|
|
9
9
|
max_decimal_places = current_schema.schema['maxDecimal']
|
10
|
-
s = data.to_s.split(
|
10
|
+
s = data.to_s.split('.')[1]
|
11
11
|
if s && s.length > max_decimal_places
|
12
12
|
message = "The property '#{build_fragment(fragments)}' had more decimal places than the allowed #{max_decimal_places}"
|
13
13
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
@@ -4,12 +4,12 @@ module JSON
|
|
4
4
|
class Schema
|
5
5
|
class NotAttribute < Attribute
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
-
schema = JSON::Schema.new(current_schema.schema['not'],current_schema.uri,validator)
|
7
|
+
schema = JSON::Schema.new(current_schema.schema['not'], current_schema.uri, validator)
|
8
8
|
failed = true
|
9
9
|
errors_copy = processor.validation_errors.clone
|
10
10
|
|
11
11
|
begin
|
12
|
-
schema.validate(data,fragments,processor,options)
|
12
|
+
schema.validate(data, fragments, processor, options)
|
13
13
|
# If we're recording errors, we don't throw an exception. Instead, check the errors array length
|
14
14
|
if options[:record_errors] && errors_copy.length != processor.validation_errors.length
|
15
15
|
processor.validation_errors.replace(errors_copy)
|
@@ -15,10 +15,10 @@ module JSON
|
|
15
15
|
valid = false
|
16
16
|
|
17
17
|
one_of.each_with_index do |element, schema_index|
|
18
|
-
schema = JSON::Schema.new(element,current_schema.uri,validator)
|
18
|
+
schema = JSON::Schema.new(element, current_schema.uri, validator)
|
19
19
|
pre_validation_error_count = validation_errors(processor).count
|
20
20
|
begin
|
21
|
-
schema.validate(data,fragments,processor,options)
|
21
|
+
schema.validate(data, fragments, processor, options)
|
22
22
|
success_data = data.is_a?(Hash) ? data.clone : data
|
23
23
|
valid = true
|
24
24
|
rescue ValidationError
|
@@ -35,8 +35,6 @@ module JSON
|
|
35
35
|
data = original_data
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
38
|
if validation_error_count == one_of.length - 1
|
41
39
|
data = success_data
|
42
40
|
return
|
@@ -12,6 +12,7 @@ module JSON
|
|
12
12
|
# Check each key in the data hash to see if it matches the regex
|
13
13
|
data.each do |key, value|
|
14
14
|
next unless regexp.match(key)
|
15
|
+
|
15
16
|
schema = JSON::Schema.new(property_schema, current_schema.uri, validator)
|
16
17
|
schema.validate(data[key], fragments + [key], processor, options)
|
17
18
|
end
|
@@ -4,7 +4,7 @@ module JSON
|
|
4
4
|
class Schema
|
5
5
|
class PropertiesAttribute < Attribute
|
6
6
|
def self.required?(schema, options)
|
7
|
-
schema.fetch('required') { options[:
|
7
|
+
schema.fetch('required') { options[:allPropertiesRequired] }
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
@@ -15,9 +15,9 @@ module JSON
|
|
15
15
|
property = property.to_s
|
16
16
|
|
17
17
|
if !data.key?(property) &&
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
options[:insert_defaults] &&
|
19
|
+
property_schema.has_key?('default') &&
|
20
|
+
!property_schema['readonly']
|
21
21
|
default = property_schema['default']
|
22
22
|
data[property] = default.is_a?(Hash) ? default.clone : default
|
23
23
|
end
|
@@ -33,8 +33,8 @@ module JSON
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# When
|
37
|
-
return unless options[:
|
36
|
+
# When noAdditionalProperties is true, ensure no undefined properties exist in the data
|
37
|
+
return unless options[:noAdditionalProperties] == true && !schema.key?('additionalProperties')
|
38
38
|
|
39
39
|
diff = data.select do |k, v|
|
40
40
|
k = k.to_s
|
@@ -55,7 +55,7 @@ module JSON
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
unless diff.empty?
|
59
59
|
properties = diff.keys.join(', ')
|
60
60
|
message = "The property '#{build_fragment(fragments)}' contained undefined properties: '#{properties}'"
|
61
61
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
@@ -6,7 +6,7 @@ module JSON
|
|
6
6
|
# draft4 relies on its own RequiredAttribute validation at a higher level, rather than
|
7
7
|
# as an attribute of individual properties.
|
8
8
|
def self.required?(schema, options)
|
9
|
-
options[:
|
9
|
+
options[:allPropertiesRequired] == true
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class PropertyNames < Attribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
return unless data.is_a?(Hash)
|
8
|
+
|
9
|
+
propnames = current_schema.schema['propertyNames']
|
10
|
+
|
11
|
+
if propnames.is_a?(Hash)
|
12
|
+
schema = JSON::Schema.new(propnames, current_schema.uri, validator)
|
13
|
+
data.each_key do |key|
|
14
|
+
schema.validate(key, fragments + [key], processor, options)
|
15
|
+
end
|
16
|
+
elsif propnames == false && data.any?
|
17
|
+
message = "The property '#{build_fragment(fragments)}' contains additional properties #{data.keys.inspect} outside of the schema when none are allowed"
|
18
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
6
6
|
class Schema
|
7
7
|
class RefAttribute < Attribute
|
8
8
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
9
|
-
uri,schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)
|
9
|
+
uri, schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)
|
10
10
|
|
11
11
|
if schema
|
12
12
|
schema.validate(data, fragments, processor, options)
|
@@ -20,19 +20,19 @@ module JSON
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.get_referenced_uri_and_schema(s, current_schema, validator)
|
23
|
-
uri,schema = nil,nil
|
23
|
+
uri, schema = nil, nil
|
24
24
|
|
25
25
|
temp_uri = JSON::Util::URI.normalize_ref(s['$ref'], current_schema.uri)
|
26
26
|
|
27
27
|
# Grab the parent schema from the schema list
|
28
|
-
schema_key = temp_uri.to_s.split(
|
28
|
+
schema_key = temp_uri.to_s.split('#')[0] + '#'
|
29
29
|
|
30
30
|
ref_schema = JSON::Validator.schema_for_uri(schema_key)
|
31
31
|
|
32
32
|
if ref_schema
|
33
33
|
# Perform fragment resolution to retrieve the appropriate level for the schema
|
34
34
|
target_schema = ref_schema.schema
|
35
|
-
fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split(
|
35
|
+
fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split('/')
|
36
36
|
fragment_path = ''
|
37
37
|
fragments.each do |fragment|
|
38
38
|
if fragment && fragment != ''
|
@@ -44,17 +44,17 @@ module JSON
|
|
44
44
|
end
|
45
45
|
fragment_path = fragment_path + "/#{fragment}"
|
46
46
|
if target_schema.nil?
|
47
|
-
raise SchemaError
|
47
|
+
raise SchemaError, "The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri.to_s}"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
# We have the schema finally, build it and validate!
|
53
53
|
uri = temp_uri
|
54
|
-
schema = JSON::Schema.new(target_schema,temp_uri,validator)
|
54
|
+
schema = JSON::Schema.new(target_schema, temp_uri, validator)
|
55
55
|
end
|
56
56
|
|
57
|
-
[uri,schema]
|
57
|
+
[uri, schema]
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -11,11 +11,12 @@ module JSON
|
|
11
11
|
|
12
12
|
schema['required'].each do |property, property_schema|
|
13
13
|
next if data.has_key?(property.to_s)
|
14
|
+
|
14
15
|
prop_defaults = options[:insert_defaults] &&
|
15
16
|
defined_properties &&
|
16
17
|
defined_properties[property] &&
|
17
|
-
!defined_properties[property][
|
18
|
-
!defined_properties[property][
|
18
|
+
!defined_properties[property]['default'].nil? &&
|
19
|
+
!defined_properties[property]['readonly']
|
19
20
|
|
20
21
|
if !prop_defaults
|
21
22
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|