json-schema 1.0.12 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|