jschema 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/jschema.rb +41 -0
- data/lib/jschema/json_reference.rb +65 -0
- data/lib/jschema/schema.rb +84 -0
- data/lib/jschema/schema_ref.rb +13 -0
- data/lib/jschema/simple_validator.rb +86 -0
- data/lib/jschema/string_length_validator.rb +17 -0
- data/lib/jschema/validator.rb +14 -0
- data/lib/jschema/validator/all_of.rb +29 -0
- data/lib/jschema/validator/any_of.rb +29 -0
- data/lib/jschema/validator/dependencies.rb +63 -0
- data/lib/jschema/validator/enum.rb +23 -0
- data/lib/jschema/validator/format.rb +75 -0
- data/lib/jschema/validator/items.rb +79 -0
- data/lib/jschema/validator/max_items.rb +28 -0
- data/lib/jschema/validator/max_length.rb +23 -0
- data/lib/jschema/validator/max_properties.rb +31 -0
- data/lib/jschema/validator/maximum.rb +31 -0
- data/lib/jschema/validator/min_items.rb +28 -0
- data/lib/jschema/validator/min_length.rb +23 -0
- data/lib/jschema/validator/min_properties.rb +31 -0
- data/lib/jschema/validator/minimum.rb +31 -0
- data/lib/jschema/validator/multiple_of.rb +32 -0
- data/lib/jschema/validator/not.rb +23 -0
- data/lib/jschema/validator/one_of.rb +29 -0
- data/lib/jschema/validator/pattern.rb +36 -0
- data/lib/jschema/validator/properties.rb +106 -0
- data/lib/jschema/validator/required.rb +34 -0
- data/lib/jschema/validator/type.rb +57 -0
- data/lib/jschema/validator/unique_items.rb +27 -0
- data/test/assert_received.rb +15 -0
- data/test/string_length_validator_tests.rb +18 -0
- data/test/test_assert_received.rb +39 -0
- data/test/test_integration.rb +30 -0
- data/test/test_json_reference.rb +84 -0
- data/test/test_schema.rb +125 -0
- data/test/test_schema_ref.rb +11 -0
- data/test/test_validator.rb +29 -0
- data/test/validator/argument_is_array_of_schemas_tests.rb +22 -0
- data/test/validator/assertions.rb +56 -0
- data/test/validator/properties_limit_tests.rb +13 -0
- data/test/validator/schema_validation_helpers.rb +29 -0
- data/test/validator/test_all_of.rb +30 -0
- data/test/validator/test_any_of.rb +31 -0
- data/test/validator/test_dependencies.rb +106 -0
- data/test/validator/test_enum.rb +30 -0
- data/test/validator/test_format.rb +70 -0
- data/test/validator/test_items.rb +113 -0
- data/test/validator/test_max_items.rb +26 -0
- data/test/validator/test_max_length.rb +30 -0
- data/test/validator/test_max_properties.rb +29 -0
- data/test/validator/test_maximum.rb +58 -0
- data/test/validator/test_min_items.rb +27 -0
- data/test/validator/test_min_length.rb +30 -0
- data/test/validator/test_min_properties.rb +29 -0
- data/test/validator/test_minimum.rb +58 -0
- data/test/validator/test_multiple_of.rb +38 -0
- data/test/validator/test_not.rb +32 -0
- data/test/validator/test_one_of.rb +31 -0
- data/test/validator/test_pattern.rb +32 -0
- data/test/validator/test_properties.rb +136 -0
- data/test/validator/test_required.rb +30 -0
- data/test/validator/test_simple_validator.rb +100 -0
- data/test/validator/test_type.rb +97 -0
- data/test/validator/test_unique_items.rb +30 -0
- data/test/validator/validation_against_schemas_tests.rb +24 -0
- metadata +144 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class Enum < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['enum']
|
7
|
+
|
8
|
+
def validate_args(enum)
|
9
|
+
unique_non_empty_array?(enum) || invalid_schema('enum', enum)
|
10
|
+
end
|
11
|
+
|
12
|
+
def post_initialize(enum)
|
13
|
+
@enum = enum
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_instance(instance)
|
17
|
+
unless @enum.include? instance
|
18
|
+
"#{instance} must be one of: #{@enum.join(', ')}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
|
3
|
+
module JSchema
|
4
|
+
module Validator
|
5
|
+
class Format < SimpleValidator
|
6
|
+
private
|
7
|
+
|
8
|
+
self.keywords = ['format']
|
9
|
+
|
10
|
+
def validate_args(format)
|
11
|
+
allowed_formats =
|
12
|
+
['date-time', 'email', 'hostname', 'ipv4', 'ipv6', 'uri']
|
13
|
+
|
14
|
+
if allowed_formats.include?(format)
|
15
|
+
true
|
16
|
+
else
|
17
|
+
invalid_schema 'format', format
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def post_initialize(format)
|
22
|
+
@validator_method = format.gsub('-', '_')
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_instance(instance)
|
26
|
+
unless send(@validator_method, instance)
|
27
|
+
"#{instance} must be a #{@validator_method}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def applicable_types
|
32
|
+
[String]
|
33
|
+
end
|
34
|
+
|
35
|
+
def date_time(instance)
|
36
|
+
true if DateTime.rfc3339(instance)
|
37
|
+
rescue ArgumentError
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def email(instance)
|
42
|
+
instance.include? '@'
|
43
|
+
end
|
44
|
+
|
45
|
+
# Acc.to RFC 1034, 3.1
|
46
|
+
def hostname(instance)
|
47
|
+
if instance.length.between?(1, 255)
|
48
|
+
instance.split('.').all? do |label|
|
49
|
+
label =~ /^[\da-z\-]{1,63}$/i
|
50
|
+
end
|
51
|
+
else
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def ipv4(instance)
|
57
|
+
IPAddr.new(instance).ipv4?
|
58
|
+
rescue ArgumentError
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def ipv6(instance)
|
63
|
+
IPAddr.new(instance).ipv6?
|
64
|
+
rescue ArgumentError
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
def uri(instance)
|
69
|
+
URI.parse instance
|
70
|
+
rescue URI::InvalidURIError
|
71
|
+
false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class Items < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['items', 'additionalItems']
|
7
|
+
|
8
|
+
def validate_args(items, additional_items)
|
9
|
+
additional_items_valid? additional_items
|
10
|
+
items_valid? items
|
11
|
+
end
|
12
|
+
|
13
|
+
def additional_items_valid?(additional_items)
|
14
|
+
additional_items.nil? ||
|
15
|
+
boolean?(additional_items) ||
|
16
|
+
valid_schema?(additional_items, 'additionalItems') ||
|
17
|
+
invalid_schema('additionalItems', additional_items)
|
18
|
+
end
|
19
|
+
|
20
|
+
def items_valid?(items)
|
21
|
+
items.nil? ||
|
22
|
+
valid_schema?(items, 'items') ||
|
23
|
+
schema_array?(items, 'items') ||
|
24
|
+
invalid_schema('items', items)
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_initialize(items, additional_items)
|
28
|
+
@items = items
|
29
|
+
@additional_items = additional_items
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_instance(instance)
|
33
|
+
validate_additional_items(instance) ||
|
34
|
+
validate_all_items(instance)
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_additional_items(instance)
|
38
|
+
if @additional_items == false &&
|
39
|
+
@items.is_a?(Array) &&
|
40
|
+
@items.size < instance.size
|
41
|
+
|
42
|
+
"#{instance} must not contain any additional items"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate_all_items(instance)
|
47
|
+
instance.to_enum.each_with_index do |item, index|
|
48
|
+
schema = schema_for_item(index)
|
49
|
+
validation_errors = schema.validate(item)
|
50
|
+
unless validation_errors.empty?
|
51
|
+
return validation_errors.first
|
52
|
+
end
|
53
|
+
end
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def schema_for_item(index)
|
58
|
+
case @items
|
59
|
+
when Array
|
60
|
+
if index < @items.size
|
61
|
+
Schema.build @items[index], parent, "items/#{index}"
|
62
|
+
elsif @additional_items.is_a?(Hash)
|
63
|
+
Schema.build @additional_items, parent, 'additionalItems'
|
64
|
+
else
|
65
|
+
Schema.build
|
66
|
+
end
|
67
|
+
when Hash
|
68
|
+
Schema.build @items, parent, 'items'
|
69
|
+
else
|
70
|
+
fail UnknownError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def applicable_types
|
75
|
+
[Array]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MaxItems < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['maxItems']
|
7
|
+
|
8
|
+
def validate_args(max_items)
|
9
|
+
greater_or_equal_to?(max_items, 0) ||
|
10
|
+
invalid_schema('maxItems', max_items)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_initialize(max_items)
|
14
|
+
@max_items = max_items
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_instance(instance)
|
18
|
+
if instance.size > @max_items
|
19
|
+
"#{instance} has too many items"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def applicable_types
|
24
|
+
[Array]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MaxLength < StringLengthValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['maxLength']
|
7
|
+
|
8
|
+
def validate_args(max_length)
|
9
|
+
if valid_length_limit?(max_length, 1)
|
10
|
+
true
|
11
|
+
else
|
12
|
+
invalid_schema 'maxLength', max_length
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_instance(instance)
|
17
|
+
if instance.size > @length_limit
|
18
|
+
"#{instance} is too long"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MaxProperties < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['maxProperties']
|
7
|
+
|
8
|
+
def validate_args(max_properties)
|
9
|
+
if greater_or_equal_to?(max_properties, 0)
|
10
|
+
true
|
11
|
+
else
|
12
|
+
invalid_schema 'maxProperties', max_properties
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_initialize(max_properties)
|
17
|
+
@max_properties = max_properties
|
18
|
+
end
|
19
|
+
|
20
|
+
def applicable_types
|
21
|
+
[Hash]
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_instance(instance)
|
25
|
+
if instance.keys.size > @max_properties
|
26
|
+
"#{instance} has too many properties"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class Maximum < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['maximum', 'exclusiveMaximum']
|
7
|
+
|
8
|
+
def validate_args(maximum, exclusive_maximum)
|
9
|
+
number?(maximum) || invalid_schema('maximum', maximum)
|
10
|
+
exclusive_maximum.nil? || boolean?(exclusive_maximum) ||
|
11
|
+
invalid_schema('exclusiveMaximum', exclusive_maximum)
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_initialize(maximum, exclusive_maximum)
|
15
|
+
@maximum = maximum
|
16
|
+
@exclusive_maximum = exclusive_maximum
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_instance(instance)
|
20
|
+
method = @exclusive_maximum ? :< : :<=
|
21
|
+
unless instance.public_send(method, @maximum)
|
22
|
+
"#{instance} must be #{method} than #{@maximum}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def applicable_types
|
27
|
+
[Fixnum, Bignum, Float, BigDecimal]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MinItems < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['minItems']
|
7
|
+
|
8
|
+
def validate_args(min_items)
|
9
|
+
greater_or_equal_to?(min_items, 0) ||
|
10
|
+
invalid_schema('minItems', min_items)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_initialize(min_items)
|
14
|
+
@min_items = min_items
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_instance(instance)
|
18
|
+
if instance.size < @min_items
|
19
|
+
"#{instance} has too few items"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def applicable_types
|
24
|
+
[Array]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MinLength < JSchema::StringLengthValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['minLength']
|
7
|
+
|
8
|
+
def validate_args(min_length)
|
9
|
+
if valid_length_limit?(min_length, 0)
|
10
|
+
true
|
11
|
+
else
|
12
|
+
invalid_schema 'minLength', min_length
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_instance(instance)
|
17
|
+
if instance.size < @length_limit
|
18
|
+
"#{instance} is too short"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MinProperties < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['minProperties']
|
7
|
+
|
8
|
+
def validate_args(min_properties)
|
9
|
+
if greater_or_equal_to?(min_properties, 0)
|
10
|
+
true
|
11
|
+
else
|
12
|
+
invalid_schema 'minProperties', min_properties
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_initialize(min_properties)
|
17
|
+
@min_properties = min_properties
|
18
|
+
end
|
19
|
+
|
20
|
+
def applicable_types
|
21
|
+
[Hash]
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_instance(instance)
|
25
|
+
if instance.keys.size < @min_properties
|
26
|
+
"#{instance} has too few properties"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class Minimum < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['minimum', 'exclusiveMinimum']
|
7
|
+
|
8
|
+
def validate_args(minimum, exclusive_minimum)
|
9
|
+
number?(minimum) || invalid_schema('minimum', minimum)
|
10
|
+
exclusive_minimum.nil? || boolean?(exclusive_minimum) ||
|
11
|
+
invalid_schema('exclusiveMinimum', exclusive_minimum)
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_initialize(minimum, exclusive_minimum)
|
15
|
+
@minimum = minimum
|
16
|
+
@exclusive_minimum = exclusive_minimum
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_instance(instance)
|
20
|
+
method = @exclusive_minimum ? :> : :>=
|
21
|
+
unless instance.public_send(method, @minimum)
|
22
|
+
"#{instance} must be #{method} than #{@minimum}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def applicable_types
|
27
|
+
[Fixnum, Bignum, Float, BigDecimal]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module JSchema
|
2
|
+
module Validator
|
3
|
+
class MultipleOf < SimpleValidator
|
4
|
+
private
|
5
|
+
|
6
|
+
self.keywords = ['multipleOf']
|
7
|
+
|
8
|
+
def validate_args(multiple_of)
|
9
|
+
if number?(multiple_of) && multiple_of > 0
|
10
|
+
true
|
11
|
+
else
|
12
|
+
invalid_schema('multipleOf', multiple_of)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_initialize(multiple_of)
|
17
|
+
@multiple_of = multiple_of
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_instance(instance)
|
21
|
+
div_remainder = instance.abs % @multiple_of
|
22
|
+
unless div_remainder.abs < 1e-6
|
23
|
+
"#{instance} must be a multiple of #{@multiple_of}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def applicable_types
|
28
|
+
[Fixnum, Bignum, Float, BigDecimal]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|