json-schema 0.9.12 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +3 -3
- data/lib/json-schema/attributes/additionalitems.rb +2 -2
- data/lib/json-schema/attributes/additionalproperties.rb +2 -2
- data/lib/json-schema/attributes/dependencies.rb +3 -3
- data/lib/json-schema/attributes/disallow.rb +1 -1
- data/lib/json-schema/attributes/divisibleby.rb +1 -1
- data/lib/json-schema/attributes/enum.rb +1 -1
- data/lib/json-schema/attributes/extends.rb +1 -1
- data/lib/json-schema/attributes/format.rb +31 -23
- data/lib/json-schema/attributes/items.rb +2 -2
- data/lib/json-schema/attributes/maxdecimal.rb +1 -1
- data/lib/json-schema/attributes/maximum.rb +1 -1
- data/lib/json-schema/attributes/maximum_inclusive.rb +1 -1
- data/lib/json-schema/attributes/maxitems.rb +1 -1
- data/lib/json-schema/attributes/maxlength.rb +1 -1
- data/lib/json-schema/attributes/minimum.rb +1 -1
- data/lib/json-schema/attributes/minimum_inclusive.rb +1 -1
- data/lib/json-schema/attributes/minitems.rb +1 -1
- data/lib/json-schema/attributes/minlength.rb +1 -1
- data/lib/json-schema/attributes/pattern.rb +1 -1
- data/lib/json-schema/attributes/patternproperties.rb +1 -1
- data/lib/json-schema/attributes/properties.rb +2 -2
- data/lib/json-schema/attributes/properties_optional.rb +2 -2
- data/lib/json-schema/attributes/ref.rb +3 -2
- data/lib/json-schema/attributes/type.rb +3 -3
- data/lib/json-schema/attributes/uniqueitems.rb +1 -1
- data/lib/json-schema/schema.rb +2 -2
- data/lib/json-schema/validator.rb +35 -5
- data/test/test_full_validation.rb +40 -0
- metadata +39 -33
data/README.textile
CHANGED
@@ -18,15 +18,15 @@ From the git repo:
|
|
18
18
|
|
19
19
|
<pre>
|
20
20
|
$ gem build json-schema.gemspec
|
21
|
-
$ gem install json-schema-0.
|
21
|
+
$ gem install json-schema-1.0.0.gem
|
22
22
|
</pre>
|
23
23
|
|
24
24
|
|
25
25
|
h2. Usage
|
26
26
|
|
27
|
-
|
27
|
+
Three base validation methods exist: <code>validate</code>, <code>validate!</code>, and <code>fully_validate</code>. The first returns a boolean on whether a validation attempt passes and the second will throw a <code>JSON::Schema::ValidationError</code> with an appropriate message/trace on where the validation failed. The third validation method does not immediately fail upon a validation error and instead builds an array of validation errors return when validation is complete.
|
28
28
|
|
29
|
-
|
29
|
+
All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to these methods is always the schema, the second is always the data to validate. An optional third options argument is also accepted; available options are used in the examples below.
|
30
30
|
|
31
31
|
By default, the validator uses the "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03 specification for validation; however, the user is free to specify additional specifications or extend existing ones. Legacy support for Draft 1 and Draft 2 is included by either passing an optional <code>:version</code> parameter to the <code>validate</code> method (set either as <code>:draft1</code> or <code>draft2</code>), or by declaring the <code>$schema</code> attribute in the schema and referencing the appropriate specification URI. Note that the <code>$schema</code> attribute takes precedence over the <code>:version</code> option during parsing and validation.
|
32
32
|
|
@@ -5,13 +5,13 @@ module JSON
|
|
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
|
-
|
8
|
+
validation_error(message, fragments, current_schema, 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)
|
14
|
+
schema.validate(item, fragments, options)
|
15
15
|
fragments.pop
|
16
16
|
end
|
17
17
|
end
|
@@ -23,12 +23,12 @@ module JSON
|
|
23
23
|
|
24
24
|
if current_schema.schema['additionalProperties'] == false && !extra_properties.empty?
|
25
25
|
message = "The property '#{build_fragment(fragments)}' contains additional properties outside of the schema when none are allowed"
|
26
|
-
|
26
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
27
27
|
elsif current_schema.schema['additionalProperties'].is_a?(Hash)
|
28
28
|
extra_properties.each do |key|
|
29
29
|
schema = JSON::Schema.new(current_schema.schema['additionalProperties'],current_schema.uri,validator)
|
30
30
|
fragments << key
|
31
|
-
schema.validate(data[key],fragments)
|
31
|
+
schema.validate(data[key],fragments,options)
|
32
32
|
fragments.pop
|
33
33
|
end
|
34
34
|
end
|
@@ -8,18 +8,18 @@ module JSON
|
|
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
|
-
|
11
|
+
validation_error(message, fragments, current_schema, 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
|
-
|
17
|
+
validation_error(message, fragments, current_schema, 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)
|
22
|
+
schema.validate(data, fragments, options)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -3,7 +3,7 @@ module JSON
|
|
3
3
|
class DisallowAttribute < Attribute
|
4
4
|
def self.validate(current_schema, data, fragments, validator, options = {})
|
5
5
|
if validator.attributes['type']
|
6
|
-
validator.attributes['type'].validate(current_schema, data, fragments, validator, {:disallow => true})
|
6
|
+
validator.attributes['type'].validate(current_schema, data, fragments, validator, {:disallow => true}.merge(options))
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -7,7 +7,7 @@ module JSON
|
|
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
|
-
|
10
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -8,24 +8,27 @@ module JSON
|
|
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"
|
11
|
-
|
11
|
+
validation_error(error_message, fragments, current_schema, 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)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
|
-
|
18
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
19
|
+
return
|
19
20
|
end
|
20
21
|
begin
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[1].to_i > 23
|
23
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[2].to_i > 59
|
24
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[3].to_i > 59
|
24
25
|
rescue Exception
|
25
|
-
|
26
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
27
|
+
return
|
26
28
|
end
|
27
29
|
else
|
28
|
-
|
30
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
31
|
+
return
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
@@ -33,16 +36,18 @@ module JSON
|
|
33
36
|
when 'date'
|
34
37
|
if data.is_a?(String)
|
35
38
|
error_message = "The property '#{build_fragment(fragments)}' must be a date in the format of YYYY-MM-DD"
|
36
|
-
|
39
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if !data.is_a?(String)
|
37
40
|
r = Regexp.new('^\d\d\d\d-\d\d-\d\d$')
|
38
41
|
if (m = r.match(data))
|
39
42
|
begin
|
40
43
|
Date.parse(data)
|
41
44
|
rescue Exception
|
42
|
-
|
45
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
46
|
+
return
|
43
47
|
end
|
44
48
|
else
|
45
|
-
|
49
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
50
|
+
return
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
@@ -50,14 +55,15 @@ module JSON
|
|
50
55
|
when 'time'
|
51
56
|
if data.is_a?(String)
|
52
57
|
error_message = "The property '#{build_fragment(fragments)}' must be a time in the format of hh:mm:ss"
|
53
|
-
|
58
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if !data.is_a?(String)
|
54
59
|
r = Regexp.new('^(\d\d):(\d\d):(\d\d)$')
|
55
60
|
if (m = r.match(data))
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[1].to_i > 23
|
62
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[2].to_i > 59
|
63
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[3].to_i > 59
|
59
64
|
else
|
60
|
-
|
65
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
66
|
+
return
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
@@ -65,14 +71,15 @@ module JSON
|
|
65
71
|
when 'ip-address', 'ipv4'
|
66
72
|
if data.is_a?(String)
|
67
73
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv4 address"
|
68
|
-
|
74
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if !data.is_a?(String)
|
69
75
|
r = Regexp.new('^(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}$')
|
70
76
|
if (m = r.match(data))
|
71
77
|
1.upto(4) do |x|
|
72
|
-
|
78
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if m[x].to_i > 255
|
73
79
|
end
|
74
80
|
else
|
75
|
-
|
81
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
82
|
+
return
|
76
83
|
end
|
77
84
|
end
|
78
85
|
|
@@ -80,22 +87,23 @@ module JSON
|
|
80
87
|
when 'ipv6'
|
81
88
|
if data.is_a?(String)
|
82
89
|
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv6 address"
|
83
|
-
|
90
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if !data.is_a?(String)
|
84
91
|
r = Regexp.new('^[a-f0-9:]+$')
|
85
92
|
if (m = r.match(data))
|
86
93
|
# All characters are valid, now validate structure
|
87
94
|
parts = data.split(":")
|
88
|
-
|
95
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if parts.length > 8
|
89
96
|
condensed_zeros = false
|
90
97
|
parts.each do |part|
|
91
98
|
if part.length == 0
|
92
|
-
|
99
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if condensed_zeros
|
93
100
|
condensed_zeros = true
|
94
101
|
end
|
95
|
-
|
102
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors]) and return if part.length > 4
|
96
103
|
end
|
97
104
|
else
|
98
|
-
|
105
|
+
validation_error(error_message, fragments, current_schema, options[:record_errors])
|
106
|
+
return
|
99
107
|
end
|
100
108
|
end
|
101
109
|
end
|
@@ -7,14 +7,14 @@ module JSON
|
|
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)
|
10
|
+
schema.validate(item,fragments, 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)
|
17
|
+
schema.validate(data[i],fragments, options)
|
18
18
|
fragments.pop
|
19
19
|
end
|
20
20
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -4,7 +4,7 @@ module JSON
|
|
4
4
|
def self.validate(current_schema, data, fragments, 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
|
-
|
7
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -5,7 +5,7 @@ module JSON
|
|
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
|
-
|
8
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -4,7 +4,7 @@ module JSON
|
|
4
4
|
def self.validate(current_schema, data, fragments, 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
|
-
|
7
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -5,7 +5,7 @@ module JSON
|
|
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
|
-
|
8
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -6,7 +6,7 @@ module JSON
|
|
6
6
|
r = Regexp.new(current_schema.schema['pattern'])
|
7
7
|
if (r.match(data)).nil?
|
8
8
|
message = "The property '#{build_fragment(fragments)}' did not match the regex '#{current_schema.schema['pattern']}'"
|
9
|
-
|
9
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -6,13 +6,13 @@ module JSON
|
|
6
6
|
current_schema.schema['properties'].each do |property,property_schema|
|
7
7
|
if (property_schema['required'] && !data.has_key?(property))
|
8
8
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
9
|
-
|
9
|
+
validation_error(message, fragments, current_schema, 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)
|
15
|
+
schema.validate(data[property],fragments,options)
|
16
16
|
fragments.pop
|
17
17
|
end
|
18
18
|
end
|
@@ -6,13 +6,13 @@ module JSON
|
|
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
|
-
|
9
|
+
validation_error(message, fragments, current_schema, 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)
|
15
|
+
schema.validate(data[property],fragments,options)
|
16
16
|
fragments.pop
|
17
17
|
end
|
18
18
|
end
|
@@ -44,9 +44,10 @@ module JSON
|
|
44
44
|
|
45
45
|
# We have the schema finally, build it and validate!
|
46
46
|
schema = JSON::Schema.new(target_schema,temp_uri,validator)
|
47
|
-
schema.validate(data, fragments)
|
47
|
+
schema.validate(data, fragments, options)
|
48
48
|
else
|
49
|
-
|
49
|
+
message = "The referenced schema '#{temp_uri.to_s}' cannot be found"
|
50
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
@@ -42,7 +42,7 @@ module JSON
|
|
42
42
|
# Validate as a schema
|
43
43
|
schema = JSON::Schema.new(type,current_schema.uri,validator)
|
44
44
|
begin
|
45
|
-
schema.validate(data,fragments)
|
45
|
+
schema.validate(data,fragments,options)
|
46
46
|
valid = true
|
47
47
|
rescue ValidationError
|
48
48
|
# We don't care that these schemas don't validate - we only care that one validated
|
@@ -57,13 +57,13 @@ module JSON
|
|
57
57
|
message = "The property '#{build_fragment(fragments)}' matched one or more of the following types:"
|
58
58
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
59
59
|
message.chop!
|
60
|
-
|
60
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
61
61
|
end
|
62
62
|
elsif !valid
|
63
63
|
message = "The property '#{build_fragment(fragments)}' did not match one or more of the following types:"
|
64
64
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
65
65
|
message.chop!
|
66
|
-
|
66
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -7,7 +7,7 @@ module JSON
|
|
7
7
|
dupes = d.uniq!
|
8
8
|
if dupes
|
9
9
|
message = "The property '#{build_fragment(fragments)}' contained duplicated array values"
|
10
|
-
|
10
|
+
validation_error(message, fragments, current_schema, options[:record_errors])
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
data/lib/json-schema/schema.rb
CHANGED
@@ -32,6 +32,15 @@ module JSON
|
|
32
32
|
def self.build_fragment(fragments)
|
33
33
|
"#/#{fragments.join('/')}"
|
34
34
|
end
|
35
|
+
|
36
|
+
def self.validation_error(message, fragments, current_schema, record_errors)
|
37
|
+
error = ValidationError.new(message, fragments, current_schema)
|
38
|
+
if record_errors
|
39
|
+
::JSON::Validator.validation_error(error.message)
|
40
|
+
else
|
41
|
+
raise error
|
42
|
+
end
|
43
|
+
end
|
35
44
|
end
|
36
45
|
|
37
46
|
class Validator
|
@@ -55,11 +64,10 @@ module JSON
|
|
55
64
|
"#{@uri.scheme}://#{uri.host}#{uri.path}"
|
56
65
|
end
|
57
66
|
|
58
|
-
def validate(current_schema, data, fragments)
|
67
|
+
def validate(current_schema, data, fragments, options = {})
|
59
68
|
current_schema.schema.each do |attr_name,attribute|
|
60
|
-
|
61
69
|
if @attributes.has_key?(attr_name.to_s)
|
62
|
-
@attributes[attr_name.to_s].validate(current_schema, data, fragments, self)
|
70
|
+
@attributes[attr_name.to_s].validate(current_schema, data, fragments, self, options)
|
63
71
|
end
|
64
72
|
end
|
65
73
|
data
|
@@ -75,12 +83,14 @@ module JSON
|
|
75
83
|
@@default_opts = {
|
76
84
|
:list => false,
|
77
85
|
:version => nil,
|
78
|
-
:validate_schema => false
|
86
|
+
:validate_schema => false,
|
87
|
+
:record_errors => false
|
79
88
|
}
|
80
89
|
@@validators = {}
|
81
90
|
@@default_validator = nil
|
82
91
|
@@available_json_backends = []
|
83
92
|
@@json_backend = nil
|
93
|
+
@@errors = []
|
84
94
|
|
85
95
|
def initialize(schema_data, data, opts={})
|
86
96
|
@options = @@default_opts.clone.merge(opts)
|
@@ -103,6 +113,8 @@ module JSON
|
|
103
113
|
validator = JSON::Validator.validators["#{u.scheme}://#{u.host}#{u.path}"]
|
104
114
|
@options[:version] = validator
|
105
115
|
end
|
116
|
+
|
117
|
+
@validation_options = @options[:record_errors] ? {:record_errors => true} : {}
|
106
118
|
|
107
119
|
# validate the schema, if requested
|
108
120
|
if @options[:validate_schema]
|
@@ -124,8 +136,10 @@ module JSON
|
|
124
136
|
# Run a simple true/false validation of data against a schema
|
125
137
|
def validate()
|
126
138
|
begin
|
127
|
-
|
139
|
+
Validator.clear_errors
|
140
|
+
@base_schema.validate(@data,[],@validation_options)
|
128
141
|
Validator.clear_cache
|
142
|
+
@@errors
|
129
143
|
rescue JSON::Schema::ValidationError
|
130
144
|
Validator.clear_cache
|
131
145
|
raise $!
|
@@ -246,10 +260,26 @@ module JSON
|
|
246
260
|
end
|
247
261
|
alias_method 'validate2', 'validate!'
|
248
262
|
|
263
|
+
|
264
|
+
def fully_validate(schema, data, opts={})
|
265
|
+
opts[:record_errors] = true
|
266
|
+
validator = JSON::Validator.new(schema, data, opts)
|
267
|
+
validator.validate
|
268
|
+
end
|
269
|
+
|
270
|
+
|
249
271
|
def clear_cache
|
250
272
|
@@schemas = {} if @@cache_schemas == false
|
251
273
|
end
|
252
274
|
|
275
|
+
def clear_errors
|
276
|
+
@@errors = []
|
277
|
+
end
|
278
|
+
|
279
|
+
def validation_error(error)
|
280
|
+
@@errors.push(error)
|
281
|
+
end
|
282
|
+
|
253
283
|
def schemas
|
254
284
|
@@schemas
|
255
285
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/json-schema'
|
3
|
+
|
4
|
+
class JSONFullValidation < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_full_validation
|
7
|
+
if JSON::Validator.json_backend != nil
|
8
|
+
data = {"b" => {"a" => 5}}
|
9
|
+
schema = {
|
10
|
+
"$schema" => "http://json-schema.org/draft-03/schema#",
|
11
|
+
"type" => "object",
|
12
|
+
"properties" => {
|
13
|
+
"b" => {
|
14
|
+
"required" => true
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
errors = JSON::Validator.fully_validate(schema,data)
|
20
|
+
assert(errors.empty?)
|
21
|
+
|
22
|
+
data = {"c" => 5}
|
23
|
+
schema = {
|
24
|
+
"$schema" => "http://json-schema.org/draft-03/schema#",
|
25
|
+
"type" => "object",
|
26
|
+
"properties" => {
|
27
|
+
"b" => {
|
28
|
+
"required" => true
|
29
|
+
},
|
30
|
+
"c" => {
|
31
|
+
"type" => "string"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
errors = JSON::Validator.fully_validate(schema,data)
|
37
|
+
assert(errors.length == 2)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,23 +1,32 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: json-schema
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- Kenny Hoxworth
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
|
-
|
16
|
+
|
17
|
+
date: 2012-01-04 00:00:00 -05:00
|
18
|
+
default_executable:
|
13
19
|
dependencies: []
|
20
|
+
|
14
21
|
description:
|
15
22
|
email: hoxworth@gmail.com
|
16
23
|
executables: []
|
24
|
+
|
17
25
|
extensions: []
|
18
|
-
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
19
28
|
- README.textile
|
20
|
-
files:
|
29
|
+
files:
|
21
30
|
- lib/json-schema/attributes/additionalitems.rb
|
22
31
|
- lib/json-schema/attributes/additionalproperties.rb
|
23
32
|
- lib/json-schema/attributes/dependencies.rb
|
@@ -55,43 +64,40 @@ files:
|
|
55
64
|
- resources/draft-02.json
|
56
65
|
- resources/draft-03.json
|
57
66
|
- README.textile
|
58
|
-
|
59
|
-
- test/test_files.rb
|
60
|
-
- test/test_jsonschema_draft1.rb
|
61
|
-
- test/test_jsonschema_draft2.rb
|
62
|
-
- test/test_jsonschema_draft3.rb
|
63
|
-
- test/test_schema_validation.rb
|
64
|
-
- test/data/bad_data_1.json
|
65
|
-
- test/data/good_data_1.json
|
66
|
-
- test/schemas/good_schema_1.json
|
67
|
-
- test/schemas/good_schema_2.json
|
67
|
+
has_rdoc: true
|
68
68
|
homepage: http://github.com/hoxworth/json-schema/tree/master
|
69
69
|
licenses: []
|
70
|
+
|
70
71
|
post_install_message:
|
71
72
|
rdoc_options: []
|
72
|
-
|
73
|
+
|
74
|
+
require_paths:
|
73
75
|
- lib
|
74
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
requirements:
|
83
|
-
- -
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
86
90
|
requirements: []
|
91
|
+
|
87
92
|
rubyforge_project:
|
88
|
-
rubygems_version: 1.
|
93
|
+
rubygems_version: 1.3.6
|
89
94
|
signing_key:
|
90
95
|
specification_version: 3
|
91
96
|
summary: Ruby JSON Schema Validator
|
92
|
-
test_files:
|
97
|
+
test_files:
|
93
98
|
- test/test_extended_schema.rb
|
94
99
|
- test/test_files.rb
|
100
|
+
- test/test_full_validation.rb
|
95
101
|
- test/test_jsonschema_draft1.rb
|
96
102
|
- test/test_jsonschema_draft2.rb
|
97
103
|
- test/test_jsonschema_draft3.rb
|