json-schema 2.8.1 → 6.1.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.
- checksums.yaml +4 -4
- data/README.md +55 -11
- data/lib/json-schema/attribute.rb +15 -16
- data/lib/json-schema/attributes/additionalitems.rb +1 -0
- data/lib/json-schema/attributes/additionalproperties.rb +4 -7
- data/lib/json-schema/attributes/allof.rb +33 -6
- data/lib/json-schema/attributes/anyof.rb +4 -4
- 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/divisibleby.rb +1 -1
- data/lib/json-schema/attributes/enum.rb +3 -3
- data/lib/json-schema/attributes/extends.rb +10 -8
- data/lib/json-schema/attributes/format.rb +2 -1
- data/lib/json-schema/attributes/formats/custom.rb +5 -7
- data/lib/json-schema/attributes/formats/date.rb +2 -1
- data/lib/json-schema/attributes/formats/date_time.rb +4 -3
- data/lib/json-schema/attributes/formats/date_time_v4.rb +2 -1
- data/lib/json-schema/attributes/formats/ip.rb +3 -3
- data/lib/json-schema/attributes/formats/time.rb +1 -1
- data/lib/json-schema/attributes/formats/uri.rb +2 -1
- data/lib/json-schema/attributes/items.rb +1 -0
- data/lib/json-schema/attributes/limit.rb +2 -2
- data/lib/json-schema/attributes/limits/numeric.rb +1 -1
- data/lib/json-schema/attributes/maxdecimal.rb +2 -2
- data/lib/json-schema/attributes/not.rb +2 -2
- data/lib/json-schema/attributes/oneof.rb +9 -11
- data/lib/json-schema/attributes/pattern.rb +1 -1
- data/lib/json-schema/attributes/patternproperties.rb +2 -1
- data/lib/json-schema/attributes/properties.rb +10 -10
- data/lib/json-schema/attributes/properties_v4.rb +2 -2
- data/lib/json-schema/attributes/propertynames.rb +23 -0
- data/lib/json-schema/attributes/ref.rb +19 -18
- data/lib/json-schema/attributes/required.rb +6 -5
- data/lib/json-schema/attributes/type.rb +11 -10
- data/lib/json-schema/attributes/type_v4.rb +3 -3
- data/lib/json-schema/attributes/uniqueitems.rb +1 -1
- data/lib/json-schema/errors/validation_error.rb +10 -10
- data/lib/json-schema/schema/reader.rb +4 -2
- data/lib/json-schema/schema/validator.rb +4 -4
- data/lib/json-schema/schema.rb +13 -14
- data/lib/json-schema/util/array_set.rb +2 -4
- data/lib/json-schema/util/uri.rb +100 -77
- data/lib/json-schema/util/uuid.rb +204 -226
- data/lib/json-schema/validator.rb +173 -156
- 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 +3 -3
- data/resources/draft-06.json +12 -12
- metadata +60 -32
|
@@ -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
|
|
@@ -27,26 +27,24 @@ module JSON
|
|
|
27
27
|
|
|
28
28
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
29
29
|
valid = false if diff > 0
|
|
30
|
-
validation_error_count += 1
|
|
30
|
+
validation_error_count += 1 unless valid
|
|
31
31
|
while diff > 0
|
|
32
|
-
diff
|
|
32
|
+
diff -= 1
|
|
33
33
|
errors["oneOf ##{schema_index}"].push(validation_errors(processor).pop)
|
|
34
34
|
end
|
|
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
|
|
43
41
|
end
|
|
44
42
|
|
|
45
|
-
if validation_error_count == one_of.length
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
message = if validation_error_count == one_of.length
|
|
44
|
+
"The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} did not match any of the required schemas"
|
|
45
|
+
else
|
|
46
|
+
"The property '#{build_fragment(fragments)}' of type #{type_of_data(data)} matched more than one of the required schemas"
|
|
47
|
+
end
|
|
50
48
|
|
|
51
49
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors]) if message
|
|
52
50
|
validation_errors(processor).last.sub_errors = errors if message
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class PatternAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(String)
|
|
8
8
|
|
|
9
9
|
pattern = current_schema.schema['pattern']
|
|
@@ -10,8 +10,9 @@ module JSON
|
|
|
10
10
|
regexp = Regexp.new(property)
|
|
11
11
|
|
|
12
12
|
# Check each key in the data hash to see if it matches the regex
|
|
13
|
-
data.each do |key,
|
|
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,15 +33,15 @@ 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
|
-
diff = data.select do |k,
|
|
39
|
+
diff = data.select do |k, _v|
|
|
40
40
|
k = k.to_s
|
|
41
41
|
|
|
42
42
|
if schema.has_key?('patternProperties')
|
|
43
43
|
match = false
|
|
44
|
-
schema['patternProperties'].each do |property,
|
|
44
|
+
schema['patternProperties'].each do |property, _property_schema|
|
|
45
45
|
regexp = Regexp.new(property)
|
|
46
46
|
if regexp.match(k)
|
|
47
47
|
match = true
|
|
@@ -55,10 +55,10 @@ 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
|
-
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
61
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors], diff.keys)
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -5,8 +5,8 @@ module JSON
|
|
|
5
5
|
class PropertiesV4Attribute < PropertiesAttribute
|
|
6
6
|
# draft4 relies on its own RequiredAttribute validation at a higher level, rather than
|
|
7
7
|
# as an attribute of individual properties.
|
|
8
|
-
def self.required?(
|
|
9
|
-
options[:
|
|
8
|
+
def self.required?(_schema, 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,12 +6,12 @@ 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)
|
|
13
13
|
elsif uri
|
|
14
|
-
message = "The referenced schema '#{uri
|
|
14
|
+
message = "The referenced schema '#{uri}' cannot be found"
|
|
15
15
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
16
16
|
else
|
|
17
17
|
message = "The property '#{build_fragment(fragments)}' was not a valid schema"
|
|
@@ -20,41 +20,42 @@ module JSON
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def self.get_referenced_uri_and_schema(s, current_schema, validator)
|
|
23
|
-
uri
|
|
23
|
+
uri = nil
|
|
24
|
+
schema = nil
|
|
24
25
|
|
|
25
26
|
temp_uri = JSON::Util::URI.normalize_ref(s['$ref'], current_schema.uri)
|
|
26
27
|
|
|
27
28
|
# Grab the parent schema from the schema list
|
|
28
|
-
schema_key = temp_uri.to_s.split(
|
|
29
|
+
schema_key = temp_uri.to_s.split('#')[0] + '#'
|
|
29
30
|
|
|
30
31
|
ref_schema = JSON::Validator.schema_for_uri(schema_key)
|
|
31
32
|
|
|
32
33
|
if ref_schema
|
|
33
34
|
# Perform fragment resolution to retrieve the appropriate level for the schema
|
|
34
35
|
target_schema = ref_schema.schema
|
|
35
|
-
fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split(
|
|
36
|
+
fragments = JSON::Util::URI.parse(JSON::Util::URI.unescape_uri(temp_uri)).fragment.split('/')
|
|
36
37
|
fragment_path = ''
|
|
37
38
|
fragments.each do |fragment|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
next unless fragment && fragment != ''
|
|
40
|
+
|
|
41
|
+
fragment = fragment.gsub('~0', '~').gsub('~1', '/')
|
|
42
|
+
target_schema = if target_schema.is_a?(Array)
|
|
43
|
+
target_schema[fragment.to_i]
|
|
44
|
+
else
|
|
45
|
+
target_schema[fragment]
|
|
46
|
+
end
|
|
47
|
+
fragment_path += "/#{fragment}"
|
|
48
|
+
if target_schema.nil?
|
|
49
|
+
raise SchemaError, "The fragment '#{fragment_path}' does not exist on schema #{ref_schema.uri}"
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
# We have the schema finally, build it and validate!
|
|
53
54
|
uri = temp_uri
|
|
54
|
-
schema = JSON::Schema.new(target_schema,temp_uri,validator)
|
|
55
|
+
schema = JSON::Schema.new(target_schema, temp_uri, validator)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
[uri,schema]
|
|
58
|
+
[uri, schema]
|
|
58
59
|
end
|
|
59
60
|
end
|
|
60
61
|
end
|
|
@@ -3,21 +3,22 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class RequiredAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(Hash)
|
|
8
8
|
|
|
9
9
|
schema = current_schema.schema
|
|
10
10
|
defined_properties = schema['properties']
|
|
11
11
|
|
|
12
|
-
schema['required'].each do |property,
|
|
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
|
+
unless prop_defaults
|
|
21
22
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
|
22
23
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
23
24
|
end
|
|
@@ -5,13 +5,13 @@ module JSON
|
|
|
5
5
|
class TypeAttribute < Attribute
|
|
6
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
|
7
7
|
union = true
|
|
8
|
-
if options[:disallow]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
types = if options[:disallow]
|
|
9
|
+
current_schema.schema['disallow']
|
|
10
|
+
else
|
|
11
|
+
current_schema.schema['type']
|
|
12
|
+
end
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
unless types.is_a?(Array)
|
|
15
15
|
types = [types]
|
|
16
16
|
union = false
|
|
17
17
|
end
|
|
@@ -25,14 +25,14 @@ module JSON
|
|
|
25
25
|
valid = data_valid_for_type?(data, type)
|
|
26
26
|
elsif type.is_a?(Hash) && union
|
|
27
27
|
# Validate as a schema
|
|
28
|
-
schema = JSON::Schema.new(type,current_schema.uri,validator)
|
|
28
|
+
schema = JSON::Schema.new(type, current_schema.uri, validator)
|
|
29
29
|
|
|
30
30
|
# We're going to add a little cruft here to try and maintain any validation errors that occur in this union type
|
|
31
31
|
# We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto a union error
|
|
32
32
|
pre_validation_error_count = validation_errors(processor).count
|
|
33
33
|
|
|
34
34
|
begin
|
|
35
|
-
schema.validate(data,fragments,processor,options.merge(:
|
|
35
|
+
schema.validate(data, fragments, processor, options.merge(disallow: false))
|
|
36
36
|
valid = true
|
|
37
37
|
rescue ValidationError
|
|
38
38
|
# We don't care that these schemas don't validate - we only care that one validated
|
|
@@ -41,7 +41,7 @@ module JSON
|
|
|
41
41
|
diff = validation_errors(processor).count - pre_validation_error_count
|
|
42
42
|
valid = false if diff > 0
|
|
43
43
|
while diff > 0
|
|
44
|
-
diff
|
|
44
|
+
diff -= 1
|
|
45
45
|
union_errors["type ##{type_index}"].push(validation_errors(processor).pop)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -50,7 +50,8 @@ module JSON
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
if options[:disallow]
|
|
53
|
-
return
|
|
53
|
+
return unless valid
|
|
54
|
+
|
|
54
55
|
message = "The property '#{build_fragment(fragments)}' matched one or more of the following types: #{list_types(types)}"
|
|
55
56
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
56
57
|
elsif !valid
|
|
@@ -3,10 +3,10 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class TypeV4Attribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
union = true
|
|
8
8
|
types = current_schema.schema['type']
|
|
9
|
-
|
|
9
|
+
unless types.is_a?(Array)
|
|
10
10
|
types = [types]
|
|
11
11
|
union = false
|
|
12
12
|
end
|
|
@@ -19,7 +19,7 @@ module JSON
|
|
|
19
19
|
build_fragment(fragments),
|
|
20
20
|
type_of_data(data),
|
|
21
21
|
union ? 'one or more of the following types' : 'the following type',
|
|
22
|
-
types
|
|
22
|
+
types,
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
|
@@ -3,7 +3,7 @@ require 'json-schema/attribute'
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
5
|
class UniqueItemsAttribute < Attribute
|
|
6
|
-
def self.validate(current_schema, data, fragments, processor,
|
|
6
|
+
def self.validate(current_schema, data, fragments, processor, _validator, options = {})
|
|
7
7
|
return unless data.is_a?(Array)
|
|
8
8
|
|
|
9
9
|
if data.clone.uniq!
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
module JSON
|
|
2
2
|
class Schema
|
|
3
3
|
class ValidationError < StandardError
|
|
4
|
-
INDENT =
|
|
5
|
-
attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message
|
|
4
|
+
INDENT = ' '
|
|
5
|
+
attr_accessor :fragments, :schema, :failed_attribute, :sub_errors, :message, :properties
|
|
6
6
|
|
|
7
|
-
def initialize(message, fragments, failed_attribute, schema)
|
|
7
|
+
def initialize(message, fragments, failed_attribute, schema, properties = [])
|
|
8
8
|
@fragments = fragments.clone
|
|
9
9
|
@schema = schema
|
|
10
10
|
@sub_errors = {}
|
|
11
11
|
@failed_attribute = failed_attribute
|
|
12
12
|
@message = message
|
|
13
|
+
@properties = properties
|
|
13
14
|
super(message_with_schema)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def to_string(subschema_level = 0)
|
|
17
18
|
if @sub_errors.empty?
|
|
18
|
-
subschema_level == 0 ? message_with_schema : message
|
|
19
|
+
(subschema_level == 0) ? message_with_schema : message
|
|
19
20
|
else
|
|
20
21
|
messages = ["#{message}. The schema specific errors were:\n"]
|
|
21
22
|
@sub_errors.each do |subschema, errors|
|
|
22
23
|
messages.push "- #{subschema}:"
|
|
23
|
-
messages.concat
|
|
24
|
+
messages.concat(Array(errors).map { |e| "#{INDENT}- #{e.to_string(subschema_level + 1)}" })
|
|
24
25
|
end
|
|
25
26
|
messages.map { |m| (INDENT * subschema_level) + m }.join("\n")
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def to_hash
|
|
30
|
-
base = {:
|
|
31
|
-
|
|
32
|
-
base[:errors] = @sub_errors.
|
|
31
|
+
base = { schema: @schema.uri, fragment: ::JSON::Schema::Attribute.build_fragment(fragments), message: message_with_schema, failed_attribute: @failed_attribute.to_s.split(':').last.split('Attribute').first }
|
|
32
|
+
unless @sub_errors.empty?
|
|
33
|
+
base[:errors] = @sub_errors.each_with_object({}) do |(subschema, errors), hsh|
|
|
33
34
|
subschema_sym = subschema.downcase.gsub(/\W+/, '_').to_sym
|
|
34
|
-
hsh[subschema_sym] = Array(errors).map{|e| e.to_hash}
|
|
35
|
-
hsh
|
|
35
|
+
hsh[subschema_sym] = Array(errors).map { |e| e.to_hash }
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
base
|
|
@@ -20,7 +20,7 @@ module JSON
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
22
|
def type_string
|
|
23
|
-
type == :uri ? 'URI' : type.to_s
|
|
23
|
+
(type == :uri) ? 'URI' : type.to_s
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -28,6 +28,7 @@ module JSON
|
|
|
28
28
|
# a schema should not be read.
|
|
29
29
|
class ReadRefused < ReadError
|
|
30
30
|
private
|
|
31
|
+
|
|
31
32
|
def error_message
|
|
32
33
|
"Read of #{type_string} at #{location} refused"
|
|
33
34
|
end
|
|
@@ -36,6 +37,7 @@ module JSON
|
|
|
36
37
|
# Raised by {JSON::Schema::Reader} when an attempt to read a schema fails
|
|
37
38
|
class ReadFailed < ReadError
|
|
38
39
|
private
|
|
40
|
+
|
|
39
41
|
def error_message
|
|
40
42
|
"Read of #{type_string} at #{location} failed"
|
|
41
43
|
end
|
|
@@ -118,7 +120,7 @@ module JSON
|
|
|
118
120
|
|
|
119
121
|
def read_uri(uri)
|
|
120
122
|
if accept_uri?(uri)
|
|
121
|
-
open(uri.to_s).read
|
|
123
|
+
URI.open(uri.to_s).read
|
|
122
124
|
else
|
|
123
125
|
raise JSON::Schema::ReadRefused.new(uri.to_s, :uri)
|
|
124
126
|
end
|
|
@@ -4,7 +4,7 @@ module JSON
|
|
|
4
4
|
attr_accessor :attributes, :formats, :uri, :names
|
|
5
5
|
attr_reader :default_formats
|
|
6
6
|
|
|
7
|
-
def initialize
|
|
7
|
+
def initialize
|
|
8
8
|
@attributes = {}
|
|
9
9
|
@formats = {}
|
|
10
10
|
@default_formats = {}
|
|
@@ -14,13 +14,13 @@ module JSON
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def extend_schema_definition(schema_uri)
|
|
17
|
-
warn
|
|
17
|
+
warn '[DEPRECATION NOTICE] The preferred way to extend a Validator is by subclassing, rather than #extend_schema_definition. This method will be removed in version >= 3.'
|
|
18
18
|
validator = JSON::Validator.validator_for_uri(schema_uri)
|
|
19
19
|
@attributes.merge!(validator.attributes)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def validate(current_schema, data, fragments, processor, options = {})
|
|
23
|
-
current_schema.schema.each do |attr_name,
|
|
23
|
+
current_schema.schema.each do |attr_name, _attribute|
|
|
24
24
|
if @attributes.has_key?(attr_name.to_s)
|
|
25
25
|
@attributes[attr_name.to_s].validate(current_schema, data, fragments, processor, self, options)
|
|
26
26
|
end
|
|
@@ -29,7 +29,7 @@ module JSON
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def metaschema
|
|
32
|
-
resources = File.expand_path('
|
|
32
|
+
resources = File.expand_path('../../../resources', __dir__)
|
|
33
33
|
File.join(resources, @metaschema_name)
|
|
34
34
|
end
|
|
35
35
|
end
|
data/lib/json-schema/schema.rb
CHANGED
|
@@ -2,15 +2,14 @@ require 'pathname'
|
|
|
2
2
|
|
|
3
3
|
module JSON
|
|
4
4
|
class Schema
|
|
5
|
-
|
|
6
5
|
attr_accessor :schema, :uri, :validator
|
|
7
6
|
|
|
8
|
-
def initialize(schema,uri,parent_validator=nil)
|
|
7
|
+
def initialize(schema, uri, parent_validator = nil)
|
|
9
8
|
@schema = schema
|
|
10
9
|
@uri = uri
|
|
11
10
|
|
|
12
11
|
# If there is an ID on this schema, use it to generate the URI
|
|
13
|
-
if @schema['id']
|
|
12
|
+
if @schema['id'].is_a?(String)
|
|
14
13
|
temp_uri = JSON::Util::URI.parse(@schema['id'])
|
|
15
14
|
if temp_uri.relative?
|
|
16
15
|
temp_uri = uri.join(temp_uri)
|
|
@@ -20,13 +19,13 @@ module JSON
|
|
|
20
19
|
@uri = JSON::Util::URI.strip_fragment(@uri)
|
|
21
20
|
|
|
22
21
|
# If there is a $schema on this schema, use it to determine which validator to use
|
|
23
|
-
if @schema['$schema']
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
@validator = if @schema['$schema']
|
|
23
|
+
JSON::Validator.validator_for_uri(@schema['$schema'])
|
|
24
|
+
elsif parent_validator
|
|
25
|
+
parent_validator
|
|
26
|
+
else
|
|
27
|
+
JSON::Validator.default_validator
|
|
28
|
+
end
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def validate(data, fragments, processor, options = {})
|
|
@@ -35,13 +34,13 @@ module JSON
|
|
|
35
34
|
|
|
36
35
|
def self.stringify(schema)
|
|
37
36
|
case schema
|
|
38
|
-
when Hash
|
|
39
|
-
|
|
40
|
-
when Array
|
|
37
|
+
when Hash
|
|
38
|
+
schema.map { |key, _value| [key.to_s, stringify(schema[key])] }.to_h
|
|
39
|
+
when Array
|
|
41
40
|
schema.map do |schema_item|
|
|
42
41
|
stringify(schema_item)
|
|
43
42
|
end
|
|
44
|
-
when Symbol
|
|
43
|
+
when Symbol
|
|
45
44
|
schema.to_s
|
|
46
45
|
else
|
|
47
46
|
schema
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
|
|
3
1
|
# This is a hack that I don't want to ever use anywhere else or repeat EVER, but we need enums to be
|
|
4
2
|
# an Array to pass schema validation. But we also want fast lookup!
|
|
5
3
|
|
|
6
4
|
class ArraySet < Array
|
|
7
5
|
def include?(obj)
|
|
8
|
-
|
|
6
|
+
unless defined? @values
|
|
9
7
|
@values = Set.new
|
|
10
|
-
|
|
8
|
+
each { |x| @values << convert_to_float_if_numeric(x) }
|
|
11
9
|
end
|
|
12
10
|
@values.include?(convert_to_float_if_numeric(obj))
|
|
13
11
|
end
|