json-schema 2.2.5 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/README.textile +1 -1
- data/lib/json-schema.rb +1 -0
- data/lib/json-schema/attribute.rb +43 -0
- data/lib/json-schema/attributes/additionalitems.rb +3 -1
- data/lib/json-schema/attributes/additionalproperties.rb +1 -0
- data/lib/json-schema/attributes/allof.rb +6 -4
- data/lib/json-schema/attributes/anyof.rb +7 -5
- data/lib/json-schema/attributes/dependencies.rb +3 -1
- data/lib/json-schema/attributes/dependencies_v4.rb +3 -1
- data/lib/json-schema/attributes/disallow.rb +3 -1
- data/lib/json-schema/attributes/divisibleby.rb +3 -1
- data/lib/json-schema/attributes/enum.rb +3 -1
- data/lib/json-schema/attributes/extends.rb +1 -0
- data/lib/json-schema/attributes/format.rb +6 -112
- data/lib/json-schema/attributes/formats/custom.rb +22 -0
- data/lib/json-schema/attributes/formats/date.rb +25 -0
- data/lib/json-schema/attributes/formats/date_time.rb +35 -0
- data/lib/json-schema/attributes/formats/ip4.rb +22 -0
- data/lib/json-schema/attributes/formats/ip6.rb +30 -0
- data/lib/json-schema/attributes/formats/time.rb +22 -0
- data/lib/json-schema/attributes/formats/uri.rb +18 -0
- data/lib/json-schema/attributes/items.rb +3 -1
- data/lib/json-schema/attributes/maxdecimal.rb +3 -1
- data/lib/json-schema/attributes/maximum.rb +3 -1
- data/lib/json-schema/attributes/maximum_inclusive.rb +2 -0
- data/lib/json-schema/attributes/maxitems.rb +2 -0
- data/lib/json-schema/attributes/maxlength.rb +3 -1
- data/lib/json-schema/attributes/maxproperties.rb +3 -1
- data/lib/json-schema/attributes/minimum.rb +3 -1
- data/lib/json-schema/attributes/minimum_inclusive.rb +3 -1
- data/lib/json-schema/attributes/minitems.rb +4 -2
- data/lib/json-schema/attributes/minlength.rb +3 -1
- data/lib/json-schema/attributes/minproperties.rb +3 -1
- data/lib/json-schema/attributes/multipleof.rb +3 -1
- data/lib/json-schema/attributes/not.rb +3 -1
- data/lib/json-schema/attributes/oneof.rb +2 -0
- data/lib/json-schema/attributes/pattern.rb +3 -1
- data/lib/json-schema/attributes/patternproperties.rb +3 -1
- data/lib/json-schema/attributes/properties.rb +4 -2
- data/lib/json-schema/attributes/properties_optional.rb +3 -1
- data/lib/json-schema/attributes/properties_v4.rb +2 -0
- data/lib/json-schema/attributes/ref.rb +3 -0
- data/lib/json-schema/attributes/required.rb +2 -0
- data/lib/json-schema/attributes/type.rb +6 -20
- data/lib/json-schema/attributes/type_v4.rb +3 -21
- data/lib/json-schema/attributes/uniqueitems.rb +3 -1
- data/lib/json-schema/errors/custom_format_error.rb +6 -0
- data/lib/json-schema/errors/json_parse_error.rb +6 -0
- data/lib/json-schema/errors/schema_error.rb +6 -0
- data/lib/json-schema/errors/validation_error.rb +46 -0
- data/lib/json-schema/schema.rb +1 -5
- data/lib/json-schema/schema/validator.rb +31 -0
- data/lib/json-schema/validator.rb +61 -126
- data/lib/json-schema/validators/draft1.rb +14 -1
- data/lib/json-schema/validators/draft2.rb +14 -1
- data/lib/json-schema/validators/draft3.rb +14 -2
- data/lib/json-schema/validators/draft4.rb +12 -1
- data/test/test_all_of_ref_schema.rb +29 -2
- data/test/test_any_of_ref_schema.rb +26 -0
- data/test/test_bad_schema_ref.rb +2 -2
- data/test/test_common_test_suite.rb +53 -0
- data/test/test_custom_format.rb +117 -0
- data/test/test_jsonschema_draft1.rb +12 -0
- data/test/test_jsonschema_draft2.rb +12 -0
- data/test/test_jsonschema_draft3.rb +31 -0
- data/test/test_jsonschema_draft4.rb +14 -48
- data/test/test_minitems.rb +18 -0
- metadata +21 -4
- data/test/test_suite.rb +0 -71
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
require 'uri'
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class IP4Format < FormatAttribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
if data.is_a?(String)
|
8
|
+
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv4 address"
|
9
|
+
r = Regexp.new('^(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}\.(\d+){1,3}$')
|
10
|
+
if (m = r.match(data))
|
11
|
+
1.upto(4) do |x|
|
12
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[x].to_i > 255
|
13
|
+
end
|
14
|
+
else
|
15
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
16
|
+
return
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
require 'uri'
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class IP6Format < FormatAttribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
if data.is_a?(String)
|
8
|
+
error_message = "The property '#{build_fragment(fragments)}' must be a valid IPv6 address"
|
9
|
+
r = Regexp.new('^[a-f0-9:]+$')
|
10
|
+
if (r.match(data))
|
11
|
+
# All characters are valid, now validate structure
|
12
|
+
parts = data.split(":")
|
13
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if parts.length > 8
|
14
|
+
condensed_zeros = false
|
15
|
+
parts.each do |part|
|
16
|
+
if part.length == 0
|
17
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if condensed_zeros
|
18
|
+
condensed_zeros = true
|
19
|
+
end
|
20
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if part.length > 4
|
21
|
+
end
|
22
|
+
else
|
23
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
24
|
+
return
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
require 'uri'
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class TimeFormat < FormatAttribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
if data.is_a?(String)
|
8
|
+
error_message = "The property '#{build_fragment(fragments)}' must be a time in the format of hh:mm:ss"
|
9
|
+
r = Regexp.new('^(\d\d):(\d\d):(\d\d)$')
|
10
|
+
if (m = r.match(data))
|
11
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
|
12
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
|
13
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
|
14
|
+
else
|
15
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
16
|
+
return
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
require 'uri'
|
3
|
+
module JSON
|
4
|
+
class Schema
|
5
|
+
class UriFormat < FormatAttribute
|
6
|
+
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
7
|
+
if data.is_a?(String)
|
8
|
+
error_message = "The property '#{build_fragment(fragments)}' must be a valid URI"
|
9
|
+
begin
|
10
|
+
URI.parse(URI.escape(data))
|
11
|
+
rescue URI::InvalidURIError
|
12
|
+
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
1
3
|
module JSON
|
2
4
|
class Schema
|
3
5
|
class MinItemsAttribute < Attribute
|
4
6
|
def self.validate(current_schema, data, fragments, processor, validator, options = {})
|
5
|
-
if data.is_a?(Array) && (data.
|
7
|
+
if data.is_a?(Array) && (data.size < current_schema.schema['minItems'])
|
6
8
|
message = "The property '#{build_fragment(fragments)}' did not contain a minimum number of items #{current_schema.schema['minItems']}"
|
7
9
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
12
|
-
end
|
14
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
1
3
|
module JSON
|
2
4
|
class Schema
|
3
5
|
class PropertiesAttribute < Attribute
|
@@ -13,8 +15,8 @@ module JSON
|
|
13
15
|
data[property.to_s] = (default.is_a?(Hash) ? default.clone : default)
|
14
16
|
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
+
if property_schema.fetch('required') { options[:strict] } &&
|
19
|
+
!data.has_key?(property.to_s) && !data.has_key?(property.to_sym)
|
18
20
|
message = "The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
19
21
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
20
22
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
1
3
|
module JSON
|
2
4
|
class Schema
|
3
5
|
class TypeAttribute < Attribute
|
@@ -15,10 +17,10 @@ module JSON
|
|
15
17
|
end
|
16
18
|
valid = false
|
17
19
|
|
18
|
-
# Create
|
19
|
-
union_errors = []
|
20
|
+
# Create a hash to hold errors that are generated during union validation
|
21
|
+
union_errors = Hash.new { |hsh, k| hsh[k] = [] }
|
20
22
|
|
21
|
-
types.
|
23
|
+
types.each_with_index do |type, type_index|
|
22
24
|
if type.is_a?(String)
|
23
25
|
valid = data_valid_for_type?(data, type)
|
24
26
|
elsif type.is_a?(Hash) && union
|
@@ -40,7 +42,7 @@ module JSON
|
|
40
42
|
valid = false if diff > 0
|
41
43
|
while diff > 0
|
42
44
|
diff = diff - 1
|
43
|
-
union_errors.push(validation_errors(processor).pop)
|
45
|
+
union_errors["type ##{type_index}"].push(validation_errors(processor).pop)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
@@ -70,22 +72,6 @@ module JSON
|
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
|
-
TYPE_CLASS_MAPPINGS = {
|
74
|
-
"string" => String,
|
75
|
-
"number" => Numeric,
|
76
|
-
"integer" => Integer,
|
77
|
-
"boolean" => [TrueClass, FalseClass],
|
78
|
-
"object" => Hash,
|
79
|
-
"array" => Array,
|
80
|
-
"null" => NilClass,
|
81
|
-
"any" => Object
|
82
|
-
}
|
83
|
-
|
84
|
-
def self.data_valid_for_type?(data, type)
|
85
|
-
valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true }
|
86
|
-
Array(valid_classes).any? { |c| data.is_a?(c) }
|
87
|
-
end
|
88
|
-
|
89
75
|
# Lookup Schema type of given class instance
|
90
76
|
def self.type_of_data(data)
|
91
77
|
type, klass = TYPE_CLASS_MAPPINGS.map { |k,v| [k,v] }.sort_by { |i|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json-schema/attribute'
|
2
|
+
|
1
3
|
module JSON
|
2
4
|
class Schema
|
3
5
|
class TypeV4Attribute < Attribute
|
@@ -10,9 +12,6 @@ module JSON
|
|
10
12
|
end
|
11
13
|
valid = false
|
12
14
|
|
13
|
-
# Create an array to hold errors that are generated during union validation
|
14
|
-
union_errors = []
|
15
|
-
|
16
15
|
types.each do |type|
|
17
16
|
valid = data_valid_for_type?(data, type)
|
18
17
|
break if valid
|
@@ -24,7 +23,6 @@ module JSON
|
|
24
23
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
25
24
|
message.chop!
|
26
25
|
validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
|
27
|
-
validation_errors(processor).last.sub_errors = union_errors
|
28
26
|
else
|
29
27
|
message = "The property '#{build_fragment(fragments)}' of type #{data.class} did not match the following type:"
|
30
28
|
types.each {|type| message += type.is_a?(String) ? " #{type}," : " (schema)," }
|
@@ -33,22 +31,6 @@ module JSON
|
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
36
|
-
|
37
|
-
TYPE_CLASS_MAPPINGS = {
|
38
|
-
"string" => String,
|
39
|
-
"number" => Numeric,
|
40
|
-
"integer" => Integer,
|
41
|
-
"boolean" => [TrueClass, FalseClass],
|
42
|
-
"object" => Hash,
|
43
|
-
"array" => Array,
|
44
|
-
"null" => NilClass,
|
45
|
-
"any" => Object
|
46
|
-
}
|
47
|
-
|
48
|
-
def self.data_valid_for_type?(data, type)
|
49
|
-
valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true }
|
50
|
-
Array(valid_classes).any? { |c| data.is_a?(c) }
|
51
|
-
end
|
52
34
|
end
|
53
35
|
end
|
54
|
-
end
|
36
|
+
end
|