json-schema 1.0.12 → 1.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.
- data/README.textile +2 -2
- data/lib/json-schema/attributes/additionalitems.rb +3 -3
- data/lib/json-schema/attributes/additionalproperties.rb +3 -3
- data/lib/json-schema/attributes/dependencies.rb +4 -4
- data/lib/json-schema/attributes/disallow.rb +2 -2
- data/lib/json-schema/attributes/divisibleby.rb +2 -2
- data/lib/json-schema/attributes/enum.rb +2 -2
- data/lib/json-schema/attributes/extends.rb +4 -4
- data/lib/json-schema/attributes/format.rb +24 -24
- data/lib/json-schema/attributes/items.rb +3 -3
- data/lib/json-schema/attributes/maxdecimal.rb +2 -2
- data/lib/json-schema/attributes/maximum.rb +2 -2
- data/lib/json-schema/attributes/maximum_inclusive.rb +2 -2
- data/lib/json-schema/attributes/maxitems.rb +2 -2
- data/lib/json-schema/attributes/maxlength.rb +2 -2
- data/lib/json-schema/attributes/minimum.rb +2 -2
- data/lib/json-schema/attributes/minimum_inclusive.rb +2 -2
- data/lib/json-schema/attributes/minitems.rb +2 -2
- data/lib/json-schema/attributes/minlength.rb +2 -2
- data/lib/json-schema/attributes/pattern.rb +2 -2
- data/lib/json-schema/attributes/patternproperties.rb +2 -2
- data/lib/json-schema/attributes/properties.rb +3 -3
- data/lib/json-schema/attributes/properties_optional.rb +3 -3
- data/lib/json-schema/attributes/ref.rb +4 -4
- data/lib/json-schema/attributes/type.rb +9 -9
- data/lib/json-schema/attributes/uniqueitems.rb +2 -2
- data/lib/json-schema/schema.rb +2 -2
- data/lib/json-schema/validator.rb +24 -27
- data/test/test_extended_schema.rb +1 -1
- metadata +2 -3
data/README.textile
CHANGED
@@ -18,7 +18,7 @@ From the git repo:
|
|
18
18
|
|
19
19
|
<pre>
|
20
20
|
$ gem build json-schema.gemspec
|
21
|
-
$ gem install json-schema-1.0.
|
21
|
+
$ gem install json-schema-1.1.0.gem
|
22
22
|
</pre>
|
23
23
|
|
24
24
|
|
@@ -225,7 +225,7 @@ require 'rubygems'
|
|
225
225
|
require 'json-schema'
|
226
226
|
|
227
227
|
class BitwiseAndAttribute < JSON::Schema::Attribute
|
228
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
228
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
229
229
|
if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0
|
230
230
|
message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-or']}"
|
231
231
|
raise JSON::Schema::ValidationError.new(message, fragments, current_schema)
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class AdditionalItemsAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Array) && current_schema.schema['items'].is_a?(Array)
|
6
6
|
if current_schema.schema['additionalItems'] == false && current_schema.schema['items'].length != data.length
|
7
7
|
message = "The property '#{build_fragment(fragments)}' contains additional array elements outside of the schema when none are allowed"
|
8
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
8
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
9
9
|
elsif current_schema.schema['additionalItems'].is_a?(Hash)
|
10
10
|
schema = JSON::Schema.new(current_schema.schema['additionalItems'],current_schema.uri,validator)
|
11
11
|
data.each_with_index do |item,i|
|
12
12
|
if i >= current_schema.schema['items'].length
|
13
13
|
fragments << i.to_s
|
14
|
-
schema.validate(item, fragments, options)
|
14
|
+
schema.validate(item, fragments, processor, options)
|
15
15
|
fragments.pop
|
16
16
|
end
|
17
17
|
end
|
@@ -3,7 +3,7 @@ require 'json-schema/attributes/extends'
|
|
3
3
|
module JSON
|
4
4
|
class Schema
|
5
5
|
class AdditionalPropertiesAttribute < Attribute
|
6
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
7
|
if data.is_a?(Hash)
|
8
8
|
extra_properties = data.keys
|
9
9
|
|
@@ -15,14 +15,14 @@ module JSON
|
|
15
15
|
matching_properties.each do |key|
|
16
16
|
schema = JSON::Schema.new(addprop[key] || addprop, current_schema.uri, validator)
|
17
17
|
fragments << key
|
18
|
-
schema.validate(data[key],fragments,options)
|
18
|
+
schema.validate(data[key],fragments,processor,options)
|
19
19
|
fragments.pop
|
20
20
|
end
|
21
21
|
extra_properties -= matching_properties
|
22
22
|
end
|
23
23
|
if !extra_properties.empty? and (addprop == false or (addprop.is_a?(Hash) and !addprop.empty?))
|
24
24
|
message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
|
25
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
25
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class DependenciesAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Hash)
|
6
6
|
current_schema.schema['dependencies'].each do |property,dependency_value|
|
7
7
|
if data.has_key?(property)
|
8
8
|
if dependency_value.is_a?(String)
|
9
9
|
if !data.has_key?(dependency_value)
|
10
10
|
message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{dependency_value}'"
|
11
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
11
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
12
12
|
end
|
13
13
|
elsif dependency_value.is_a?(Array)
|
14
14
|
dependency_value.each do |value|
|
15
15
|
if !data.has_key?(value)
|
16
16
|
message = "The property '#{build_fragment(fragments)}' has a property '#{property}' that depends on a missing property '#{value}'"
|
17
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
17
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
18
18
|
end
|
19
19
|
end
|
20
20
|
else
|
21
21
|
schema = JSON::Schema.new(dependency_value,current_schema.uri,validator)
|
22
|
-
schema.validate(data, fragments, options)
|
22
|
+
schema.validate(data, fragments, processor, options)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class DisallowAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if validator.attributes['type']
|
6
|
-
validator.attributes['type'].validate(current_schema, data, fragments, validator, {:disallow => true}.merge(options))
|
6
|
+
validator.attributes['type'].validate(current_schema, data, fragments, processor, validator, {:disallow => true}.merge(options))
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class DivisibleByAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
if current_schema.schema['divisibleBy'] == 0 ||
|
7
7
|
current_schema.schema['divisibleBy'] == 0.0 ||
|
8
8
|
(BigDecimal.new(data.to_s) % BigDecimal.new(current_schema.schema['divisibleBy'].to_s)).to_f != 0
|
9
9
|
message = "The property '#{build_fragment(fragments)}' was not divisible by #{current_schema.schema['divisibleBy']}"
|
10
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
10
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class EnumAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if !current_schema.schema['enum'].include?(data)
|
6
6
|
message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match one of the following values:"
|
7
7
|
current_schema.schema['enum'].each {|val|
|
@@ -16,7 +16,7 @@ module JSON
|
|
16
16
|
end
|
17
17
|
}
|
18
18
|
message.chop!
|
19
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
19
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -3,19 +3,19 @@ require 'json-schema/attributes/ref'
|
|
3
3
|
module JSON
|
4
4
|
class Schema
|
5
5
|
class ExtendsAttribute < Attribute
|
6
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
7
|
schemas = current_schema.schema['extends']
|
8
8
|
schemas = [schemas] if !schemas.is_a?(Array)
|
9
9
|
schemas.each do |s|
|
10
10
|
uri,schema = get_extended_uri_and_schema(s, current_schema, validator)
|
11
11
|
if schema
|
12
|
-
schema.validate(data, fragments, options)
|
12
|
+
schema.validate(data, fragments, processor, options)
|
13
13
|
elsif uri
|
14
14
|
message = "The extended schema '#{uri.to_s}' cannot be found"
|
15
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
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"
|
18
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
18
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,33 +1,33 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class FormatAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
case current_schema.schema['format']
|
6
6
|
|
7
7
|
# Timestamp in restricted ISO-8601 YYYY-MM-DDThh:mm:ssZ with optional decimal fraction of the second
|
8
8
|
when 'date-time'
|
9
9
|
if data.is_a?(String)
|
10
10
|
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"
|
11
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
11
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
12
12
|
r = Regexp.new('^\d\d\d\d-\d\d-\d\dT(\d\d):(\d\d):(\d\d)([\.,]\d+)?Z$')
|
13
13
|
if (m = r.match(data))
|
14
14
|
parts = data.split("T")
|
15
15
|
begin
|
16
16
|
Date.parse(parts[0])
|
17
17
|
rescue Exception
|
18
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
18
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
19
19
|
return
|
20
20
|
end
|
21
21
|
begin
|
22
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
|
23
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
|
24
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
|
22
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
|
23
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
|
24
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
|
25
25
|
rescue Exception
|
26
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
26
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
27
27
|
return
|
28
28
|
end
|
29
29
|
else
|
30
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
30
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
31
31
|
return
|
32
32
|
end
|
33
33
|
end
|
@@ -36,17 +36,17 @@ module JSON
|
|
36
36
|
when 'date'
|
37
37
|
if data.is_a?(String)
|
38
38
|
error_message = "The property '#{build_fragment(fragments)}' must be a date in the format of YYYY-MM-DD"
|
39
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
39
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
40
40
|
r = Regexp.new('^\d\d\d\d-\d\d-\d\d$')
|
41
41
|
if (m = r.match(data))
|
42
42
|
begin
|
43
43
|
Date.parse(data)
|
44
44
|
rescue Exception
|
45
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
45
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
46
46
|
return
|
47
47
|
end
|
48
48
|
else
|
49
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
49
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
50
50
|
return
|
51
51
|
end
|
52
52
|
end
|
@@ -55,14 +55,14 @@ module JSON
|
|
55
55
|
when 'time'
|
56
56
|
if data.is_a?(String)
|
57
57
|
error_message = "The property '#{build_fragment(fragments)}' must be a time in the format of hh:mm:ss"
|
58
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
58
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
59
59
|
r = Regexp.new('^(\d\d):(\d\d):(\d\d)$')
|
60
60
|
if (m = r.match(data))
|
61
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
|
62
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
|
63
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
|
61
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
|
62
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
|
63
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
|
64
64
|
else
|
65
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
65
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
66
66
|
return
|
67
67
|
end
|
68
68
|
end
|
@@ -71,14 +71,14 @@ module JSON
|
|
71
71
|
when 'ip-address', 'ipv4'
|
72
72
|
if data.is_a?(String)
|
73
73
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv4 address"
|
74
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
74
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
75
75
|
r = Regexp.new('^(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}$')
|
76
76
|
if (m = r.match(data))
|
77
77
|
1.upto(4) do |x|
|
78
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if m[x].to_i > 255
|
78
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[x].to_i > 255
|
79
79
|
end
|
80
80
|
else
|
81
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
81
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
82
82
|
return
|
83
83
|
end
|
84
84
|
end
|
@@ -87,22 +87,22 @@ module JSON
|
|
87
87
|
when 'ipv6'
|
88
88
|
if data.is_a?(String)
|
89
89
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv6 address"
|
90
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
90
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if !data.is_a?(String)
|
91
91
|
r = Regexp.new('^[a-f0-9:]+$')
|
92
92
|
if (m = r.match(data))
|
93
93
|
# All characters are valid, now validate structure
|
94
94
|
parts = data.split(":")
|
95
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if parts.length > 8
|
95
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if parts.length > 8
|
96
96
|
condensed_zeros = false
|
97
97
|
parts.each do |part|
|
98
98
|
if part.length == 0
|
99
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if condensed_zeros
|
99
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if condensed_zeros
|
100
100
|
condensed_zeros = true
|
101
101
|
end
|
102
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors]) and return if part.length > 4
|
102
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if part.length > 4
|
103
103
|
end
|
104
104
|
else
|
105
|
-
validation_error(error_message, fragments, current_schema, self, options[:record_errors])
|
105
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
106
106
|
return
|
107
107
|
end
|
108
108
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class ItemsAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Array)
|
6
6
|
if current_schema.schema['items'].is_a?(Hash)
|
7
7
|
data.each_with_index do |item,i|
|
8
8
|
schema = JSON::Schema.new(current_schema.schema['items'],current_schema.uri,validator)
|
9
9
|
fragments << i.to_s
|
10
|
-
schema.validate(item,fragments, options)
|
10
|
+
schema.validate(item,fragments, processor, options)
|
11
11
|
fragments.pop
|
12
12
|
end
|
13
13
|
elsif current_schema.schema['items'].is_a?(Array)
|
14
14
|
current_schema.schema['items'].each_with_index do |item_schema,i|
|
15
15
|
schema = JSON::Schema.new(item_schema,current_schema.uri,validator)
|
16
16
|
fragments << i.to_s
|
17
|
-
schema.validate(data[i],fragments, options)
|
17
|
+
schema.validate(data[i],fragments, processor, options)
|
18
18
|
fragments.pop
|
19
19
|
end
|
20
20
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MaxDecimalAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
s = data.to_s.split(".")[1]
|
7
7
|
if s && s.length > current_schema.schema['maxDecimal']
|
8
8
|
message = "The property '#{build_fragment(fragments)}' had more decimal places than the allowed #{current_schema.schema['maxDecimal']}"
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MaximumAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
if (current_schema.schema['exclusiveMaximum'] ? data >= current_schema.schema['maximum'] : data > current_schema.schema['maximum'])
|
7
7
|
message = "The property '#{build_fragment(fragments)}' did not have a maximum value of #{current_schema.schema['maximum']}, "
|
8
8
|
message += current_schema.schema['exclusiveMaximum'] ? 'exclusively' : 'inclusively'
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MaximumInclusiveAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
if (current_schema.schema['maximumCanEqual'] == false ? data >= current_schema.schema['maximum'] : data > current_schema.schema['maximum'])
|
7
7
|
message = "The property '#{build_fragment(fragments)}' did not have a maximum value of #{current_schema.schema['maximum']}, "
|
8
8
|
message += current_schema.schema['exclusiveMaximum'] ? 'exclusively' : 'inclusively'
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MaxItemsAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Array) && (data.compact.size > current_schema.schema['maxItems'])
|
6
6
|
message = "The property '#{build_fragment(fragments)}' did not contain a minimum number of items #{current_schema.schema['minItems']}"
|
7
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
7
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MaxLengthAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(String)
|
6
6
|
if data.length > current_schema.schema['maxLength']
|
7
7
|
message = "The property '#{build_fragment(fragments)}' was not of a maximum string length of #{current_schema.schema['maxLength']}"
|
8
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
8
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MinimumAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
if (current_schema.schema['exclusiveMinimum'] ? data <= current_schema.schema['minimum'] : data < current_schema.schema['minimum'])
|
7
7
|
message = "The property '#{build_fragment(fragments)}' did not have a minimum value of #{current_schema.schema['minimum']}, "
|
8
8
|
message += current_schema.schema['exclusiveMinimum'] ? 'exclusively' : 'inclusively'
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MinimumInclusiveAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Numeric)
|
6
6
|
if (current_schema.schema['minimumCanEqual'] == false ? data <= current_schema.schema['minimum'] : data < current_schema.schema['minimum'])
|
7
7
|
message = "The property '#{build_fragment(fragments)}' did not have a minimum value of #{current_schema.schema['minimum']}, "
|
8
8
|
message += current_schema.schema['exclusiveMinimum'] ? 'exclusively' : 'inclusively'
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MinItemsAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Array) && (data.compact.size < current_schema.schema['minItems'])
|
6
6
|
message = "The property '#{build_fragment(fragments)}' did not contain a minimum number of items #{current_schema.schema['minItems']}"
|
7
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
7
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class MinLengthAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(String)
|
6
6
|
if data.length < current_schema.schema['minLength']
|
7
7
|
message = "The property '#{build_fragment(fragments)}' was not of a minimum string length of #{current_schema.schema['minLength']}"
|
8
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
8
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class PatternAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(String)
|
6
6
|
r = Regexp.new(current_schema.schema['pattern'])
|
7
7
|
if (r.match(data)).nil?
|
8
8
|
message = "The property '#{build_fragment(fragments)}' value #{data.inspect} did not match the regex '#{current_schema.schema['pattern']}'"
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class PatternPropertiesAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Hash)
|
6
6
|
current_schema.schema['patternProperties'].each do |property,property_schema|
|
7
7
|
r = Regexp.new(property)
|
@@ -11,7 +11,7 @@ module JSON
|
|
11
11
|
if r.match(key)
|
12
12
|
schema = JSON::Schema.new(property_schema,current_schema.uri,validator)
|
13
13
|
fragments << key
|
14
|
-
schema.validate(data[key],fragments,options)
|
14
|
+
schema.validate(data[key],fragments,processor,options)
|
15
15
|
fragments.pop
|
16
16
|
end
|
17
17
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class PropertiesAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Hash)
|
6
6
|
current_schema.schema['properties'].each do |property,property_schema|
|
7
7
|
if !data.has_key?(property) and property_schema['default'] and !property_schema['readonly'] and options[:insert_defaults]
|
@@ -11,13 +11,13 @@ module JSON
|
|
11
11
|
|
12
12
|
if property_schema['required'] and !data.has_key?(property)
|
13
13
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
14
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
14
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
15
15
|
end
|
16
16
|
|
17
17
|
if data.has_key?(property)
|
18
18
|
schema = JSON::Schema.new(property_schema,current_schema.uri,validator)
|
19
19
|
fragments << property
|
20
|
-
schema.validate(data[property],fragments,options)
|
20
|
+
schema.validate(data[property],fragments,processor,options)
|
21
21
|
fragments.pop
|
22
22
|
end
|
23
23
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class PropertiesOptionalAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Hash)
|
6
6
|
current_schema.schema['properties'].each do |property,property_schema|
|
7
7
|
if ((property_schema['optional'].nil? || property_schema['optional'] == false) && !data.has_key?(property))
|
8
8
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
9
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
9
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
10
10
|
end
|
11
11
|
|
12
12
|
if data.has_key?(property)
|
13
13
|
schema = JSON::Schema.new(property_schema,current_schema.uri,validator)
|
14
14
|
fragments << property
|
15
|
-
schema.validate(data[property],fragments,options)
|
15
|
+
schema.validate(data[property],fragments,processor,options)
|
16
16
|
fragments.pop
|
17
17
|
end
|
18
18
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class RefAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
uri,schema = get_referenced_uri_and_schema(current_schema.schema, current_schema, validator)
|
6
6
|
|
7
7
|
if schema
|
8
|
-
schema.validate(data, fragments, options)
|
8
|
+
schema.validate(data, fragments, processor, options)
|
9
9
|
elsif uri
|
10
10
|
message = "The referenced schema '#{uri.to_s}' cannot be found"
|
11
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
11
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
12
12
|
else
|
13
13
|
message = "The property '#{build_fragment(fragments)}' was not a valid schema"
|
14
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
14
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class TypeAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
union = true
|
6
6
|
|
7
7
|
if options[:disallow]
|
@@ -28,20 +28,20 @@ module JSON
|
|
28
28
|
|
29
29
|
# We're going to add a little cruft here to try and maintain any validation errors that occur in this union type
|
30
30
|
# We'll handle this by keeping an error count before and after validation, extracting those errors and pushing them onto a union error
|
31
|
-
pre_validation_error_count = validation_errors.count
|
31
|
+
pre_validation_error_count = validation_errors(processor).count
|
32
32
|
|
33
33
|
begin
|
34
|
-
schema.validate(data,fragments,options)
|
34
|
+
schema.validate(data,fragments,processor,options)
|
35
35
|
valid = true
|
36
36
|
rescue ValidationError
|
37
37
|
# We don't care that these schemas don't validate - we only care that one validated
|
38
38
|
end
|
39
39
|
|
40
|
-
diff = validation_errors.count - pre_validation_error_count
|
40
|
+
diff = validation_errors(processor).count - pre_validation_error_count
|
41
41
|
valid = false if diff > 0
|
42
42
|
while diff > 0
|
43
43
|
diff = diff - 1
|
44
|
-
union_errors.push(validation_errors.pop)
|
44
|
+
union_errors.push(validation_errors(processor).pop)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -53,20 +53,20 @@ module JSON
|
|
53
53
|
message = "The property '#{build_fragment(fragments)}' matched one or more of the following types:"
|
54
54
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
55
55
|
message.chop!
|
56
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
56
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
57
57
|
end
|
58
58
|
elsif !valid
|
59
59
|
if union
|
60
60
|
message = "The property '#{build_fragment(fragments)}' of type #{data.class} did not match one or more of the following types:"
|
61
61
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
62
62
|
message.chop!
|
63
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
64
|
-
validation_errors.last.sub_errors = union_errors
|
63
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
64
|
+
validation_errors(processor).last.sub_errors = union_errors
|
65
65
|
else
|
66
66
|
message = "The property '#{build_fragment(fragments)}' of type #{data.class} did not match the following type:"
|
67
67
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
68
68
|
message.chop!
|
69
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
69
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module JSON
|
2
2
|
class Schema
|
3
3
|
class UniqueItemsAttribute < Attribute
|
4
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
4
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
5
|
if data.is_a?(Array)
|
6
6
|
d = data.clone
|
7
7
|
dupes = d.uniq!
|
8
8
|
if dupes
|
9
9
|
message = "The property '#{build_fragment(fragments)}' contained duplicated array values"
|
10
|
-
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
10
|
+
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
data/lib/json-schema/schema.rb
CHANGED
@@ -34,8 +34,8 @@ module JSON
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def validate(data, fragments, options = {})
|
38
|
-
@validator.validate(self, data, fragments, options)
|
37
|
+
def validate(data, fragments, processor, options = {})
|
38
|
+
@validator.validate(self, data, fragments, processor, options)
|
39
39
|
end
|
40
40
|
|
41
41
|
def base_uri
|
@@ -4,6 +4,7 @@ require 'pathname'
|
|
4
4
|
require 'bigdecimal'
|
5
5
|
require 'digest/sha1'
|
6
6
|
require 'date'
|
7
|
+
require 'thread'
|
7
8
|
|
8
9
|
module JSON
|
9
10
|
|
@@ -46,24 +47,24 @@ module JSON
|
|
46
47
|
end
|
47
48
|
|
48
49
|
class Attribute
|
49
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
50
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
50
51
|
end
|
51
52
|
|
52
53
|
def self.build_fragment(fragments)
|
53
54
|
"#/#{fragments.join('/')}"
|
54
55
|
end
|
55
56
|
|
56
|
-
def self.validation_error(message, fragments, current_schema, failed_attribute, record_errors)
|
57
|
+
def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors)
|
57
58
|
error = ValidationError.new(message, fragments, failed_attribute, current_schema)
|
58
59
|
if record_errors
|
59
|
-
|
60
|
+
processor.validation_error(error)
|
60
61
|
else
|
61
62
|
raise error
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
|
-
def self.validation_errors
|
66
|
-
|
66
|
+
def self.validation_errors(validator)
|
67
|
+
validator.validation_errors
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
@@ -88,10 +89,10 @@ module JSON
|
|
88
89
|
"#{@uri.scheme}://#{uri.host}#{uri.path}"
|
89
90
|
end
|
90
91
|
|
91
|
-
def validate(current_schema, data, fragments, options = {})
|
92
|
+
def validate(current_schema, data, fragments, processor, options = {})
|
92
93
|
current_schema.schema.each do |attr_name,attribute|
|
93
94
|
if @attributes.has_key?(attr_name.to_s)
|
94
|
-
@attributes[attr_name.to_s].validate(current_schema, data, fragments, self, options)
|
95
|
+
@attributes[attr_name.to_s].validate(current_schema, data, fragments, processor, self, options)
|
95
96
|
end
|
96
97
|
end
|
97
98
|
data
|
@@ -116,9 +117,9 @@ module JSON
|
|
116
117
|
@@default_validator = nil
|
117
118
|
@@available_json_backends = []
|
118
119
|
@@json_backend = nil
|
119
|
-
@@errors = []
|
120
120
|
@@serializer = nil
|
121
|
-
|
121
|
+
@@mutex = Mutex.new
|
122
|
+
|
122
123
|
def self.version_string_for(version)
|
123
124
|
# I'm not a fan of this, but it's quick and dirty to get it working for now
|
124
125
|
return "draft-03" unless version
|
@@ -140,6 +141,7 @@ module JSON
|
|
140
141
|
|
141
142
|
def initialize(schema_data, data, opts={})
|
142
143
|
@options = @@default_opts.clone.merge(opts)
|
144
|
+
@errors = []
|
143
145
|
|
144
146
|
# I'm not a fan of this, but it's quick and dirty to get it working for now
|
145
147
|
version_string = "draft-03"
|
@@ -163,22 +165,21 @@ module JSON
|
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
166
|
-
@base_schema = initialize_schema(schema_data)
|
168
|
+
@@mutex.synchronize { @base_schema = initialize_schema(schema_data) }
|
167
169
|
@data = initialize_data(data)
|
168
|
-
build_schemas(@base_schema)
|
170
|
+
@@mutex.synchronize { build_schemas(@base_schema) }
|
169
171
|
end
|
170
172
|
|
171
173
|
|
172
174
|
# Run a simple true/false validation of data against a schema
|
173
175
|
def validate()
|
174
176
|
begin
|
175
|
-
|
176
|
-
@base_schema.validate(@data,[],@validation_options)
|
177
|
+
@base_schema.validate(@data,[],self,@validation_options)
|
177
178
|
Validator.clear_cache
|
178
179
|
if @options[:errors_as_objects]
|
179
|
-
|
180
|
+
return @errors.map{|e| e.to_hash}
|
180
181
|
else
|
181
|
-
|
182
|
+
return @errors.map{|e| e.to_string}
|
182
183
|
end
|
183
184
|
rescue JSON::Schema::ValidationError
|
184
185
|
Validator.clear_cache
|
@@ -286,6 +287,14 @@ module JSON
|
|
286
287
|
end
|
287
288
|
end
|
288
289
|
|
290
|
+
def validation_error(error)
|
291
|
+
@errors.push(error)
|
292
|
+
end
|
293
|
+
|
294
|
+
def validation_errors
|
295
|
+
@errors
|
296
|
+
end
|
297
|
+
|
289
298
|
|
290
299
|
class << self
|
291
300
|
def validate(schema, data,opts={})
|
@@ -345,18 +354,6 @@ module JSON
|
|
345
354
|
@@schemas = {} if @@cache_schemas == false
|
346
355
|
end
|
347
356
|
|
348
|
-
def clear_errors
|
349
|
-
@@errors = []
|
350
|
-
end
|
351
|
-
|
352
|
-
def validation_error(error)
|
353
|
-
@@errors.push(error)
|
354
|
-
end
|
355
|
-
|
356
|
-
def validation_errors
|
357
|
-
@@errors
|
358
|
-
end
|
359
|
-
|
360
357
|
def schemas
|
361
358
|
@@schemas
|
362
359
|
end
|
@@ -2,7 +2,7 @@ require 'test/unit'
|
|
2
2
|
require File.dirname(__FILE__) + '/../lib/json-schema'
|
3
3
|
|
4
4
|
class BitwiseAndAttribute < JSON::Schema::Attribute
|
5
|
-
def self.validate(current_schema, data, fragments, validator, options = {})
|
5
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
6
6
|
if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0
|
7
7
|
message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-or']}"
|
8
8
|
raise JSON::Schema::ValidationError.new(message, fragments, self, current_schema)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: hoxworth@gmail.com
|
@@ -116,4 +116,3 @@ test_files:
|
|
116
116
|
- test/schemas/good_schema_1.json
|
117
117
|
- test/schemas/good_schema_2.json
|
118
118
|
- test/schemas/inner.schema.json
|
119
|
-
has_rdoc:
|