simple_json_schema 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -1
- data/Gemfile.lock +1 -1
- data/README.md +10 -2
- data/bin/simple_json_schema +32 -0
- data/lib/simple_json_schema.rb +8 -0
- data/lib/simple_json_schema/cache.rb +15 -0
- data/lib/simple_json_schema/checker.rb +16 -4
- data/lib/simple_json_schema/concerns/hash_acessor.rb +1 -1
- data/lib/simple_json_schema/properties_helper.rb +15 -1
- data/lib/simple_json_schema/ref_helper.rb +108 -0
- data/lib/simple_json_schema/scope.rb +74 -20
- data/lib/simple_json_schema/uri_extender.rb +19 -0
- data/lib/simple_json_schema/validator.rb +94 -14
- data/lib/simple_json_schema/validators/concerns/format.rb +2 -5
- data/lib/simple_json_schema/validators/string.rb +1 -0
- data/lib/simple_json_schema/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bfd995209a8432bc92730f10961b61d8d9e0d1e3cd1aaf06432d76654dd7d66
|
4
|
+
data.tar.gz: 043f347f1c497be224fcefdd153b23bb16024410d8d8865555c6dd752d28a2f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 016b1db271f0eada2ef8dd65ccc2eaf89294685231fe6645578b8959e20011a6418e9176333c6b1ff9f9f455d309cc232177a7b1958f7e9f84fc88994b668b77
|
7
|
+
data.tar.gz: 3c8e6f11c651ccd1537eaf5ecfb010125f837568bce1d9b07bfebd431ad5eb09c7760e8f43b1ffb62c24977276e3b9959372b2152c012a23e19f17aa81c766a2
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[![coverage report](https://gitlab.com/vliper/simple_json_schema/badges/master/coverage.svg)](https://gitlab.com/vliper/simple_json_schema/-/commits/master)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/simple_json_schema.svg)](https://badge.fury.io/rb/simple_json_schema)
|
6
6
|
|
7
|
-
This implementation of the JSON Schema validation is based on the [JSONSchemer](https://github.com/davishmcclurg/json_schemer) (
|
7
|
+
This implementation of the JSON Schema validation is based on the [JSONSchemer](https://github.com/davishmcclurg/json_schemer) (WHIT IS THE RECOMMENDED TO BE USED!), but only implement the Draft7, whit [limitations](https://gitlab.com/vliper/simple_json_schema/-/blob/master/spec/simple_json_schema/json_schema_test_suite_spec.rb#L26) and some feature embedded.
|
8
8
|
|
9
9
|
# Installation
|
10
10
|
|
@@ -64,10 +64,18 @@ Whit options is possible to improve the behavior.
|
|
64
64
|
| ---- | ----------- | ------- | -------------- |
|
65
65
|
| after_property_validation | Call after validate a Property | nil | Proc to receive Scope object |
|
66
66
|
| before_property_validation | Call before validate a Property | nil | Proc to receive Scope object |
|
67
|
-
| cache | The object to do the cache for schema
|
67
|
+
| cache | The object to do the cache for schema ref and regex | Cache class per execution | any object whit implement fetch(name) { callback } |
|
68
68
|
| cast | Cast the values | false | true/false |
|
69
69
|
| insert_defaults | Insert the default property if not defined at the validation | false | true/false |
|
70
70
|
|
71
|
+
#### Extra attributes
|
72
|
+
Some extra implementations on types (THIS IS NOT ON THE DRAFT7 DEFINITION!)
|
73
|
+
|
74
|
+
| Type | Attribute | Description | Allowed values |
|
75
|
+
| string | required | Will evaluate the `blank?` concept on the string | true/false |
|
76
|
+
| integer | required | Will enforce value != 0 | true/false |
|
77
|
+
| number | required | Will enforce value != 0.0 | true/false |
|
78
|
+
|
71
79
|
## Development
|
72
80
|
|
73
81
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'pry-byebug'
|
6
|
+
|
7
|
+
require 'simple_json_schema'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
if ARGV.size != 2
|
11
|
+
puts 'simple_json_schema <JSON_DATA> <JSON_SCHEMA>'
|
12
|
+
exit(1)
|
13
|
+
end
|
14
|
+
|
15
|
+
data = JSON.parse(ARGV[0])
|
16
|
+
schema = JSON.parse(ARGV[1])
|
17
|
+
|
18
|
+
valid = SimpleJSONSchema.valid(data, schema, resolver: proc do |uri|
|
19
|
+
if uri.host == 'localhost'
|
20
|
+
# Resolve localhost test schemas
|
21
|
+
path = Pathname.new(__dir__).join('..', 'spec', 'json-schema-test-suite', 'remotes', uri.path.delete_prefix('/'))
|
22
|
+
JSON.parse(path.read)
|
23
|
+
else
|
24
|
+
JSON.parse(::Net::HTTP.get(uri))
|
25
|
+
end
|
26
|
+
end)
|
27
|
+
|
28
|
+
if valid.empty?
|
29
|
+
puts 'valid!'
|
30
|
+
else
|
31
|
+
puts valid
|
32
|
+
end
|
data/lib/simple_json_schema.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'simple_json_schema/version'
|
4
4
|
|
5
|
+
require 'net/http'
|
6
|
+
|
5
7
|
require 'active_support/core_ext/hash'
|
6
8
|
require 'addressable/template'
|
7
9
|
require 'ecma-re-validator'
|
@@ -17,10 +19,13 @@ require 'simple_json_schema/validators/number'
|
|
17
19
|
require 'simple_json_schema/validators/string'
|
18
20
|
|
19
21
|
require 'simple_json_schema/concerns/hash_acessor'
|
22
|
+
require 'simple_json_schema/uri_extender'
|
23
|
+
require 'simple_json_schema/cache'
|
20
24
|
require 'simple_json_schema/checker'
|
21
25
|
require 'simple_json_schema/items_helper'
|
22
26
|
require 'simple_json_schema/properties_helper'
|
23
27
|
require 'simple_json_schema/regex_helper'
|
28
|
+
require 'simple_json_schema/ref_helper'
|
24
29
|
require 'simple_json_schema/scope'
|
25
30
|
require 'simple_json_schema/validator'
|
26
31
|
|
@@ -31,6 +36,7 @@ module SimpleJSONSchema
|
|
31
36
|
'http://json-schema.org/draft-07/schema#' => :draft7
|
32
37
|
}.freeze
|
33
38
|
|
39
|
+
NET_HTTP_REF_RESOLVER = proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
|
34
40
|
DEFAULT_SCHEMA = 'http://json-schema.org/draft-07/schema#'
|
35
41
|
|
36
42
|
class << self
|
@@ -48,6 +54,8 @@ module SimpleJSONSchema
|
|
48
54
|
scope = Scope.new(data: data, schema: schema, draft: draft_class(schema), options: options)
|
49
55
|
Validator.validate(scope)
|
50
56
|
scope.errors
|
57
|
+
rescue StandardError => e
|
58
|
+
scope.error(:invalid, exception: e.message)
|
51
59
|
end
|
52
60
|
|
53
61
|
private
|
@@ -2,20 +2,24 @@
|
|
2
2
|
|
3
3
|
module SimpleJSONSchema
|
4
4
|
module Checker
|
5
|
+
JSON_POINTER_REGEX_STRING = '(\/([^~\/]|~[01])*)*'
|
6
|
+
JSON_POINTER_REGEX = /\A#{JSON_POINTER_REGEX_STRING}\z/.freeze
|
7
|
+
RELATIVE_JSON_POINTER_REGEX = /\A(0|[1-9]\d*)(#|#{JSON_POINTER_REGEX_STRING})?\z/.freeze
|
8
|
+
|
5
9
|
class << self
|
6
10
|
def at_value(scope, check, operation)
|
7
11
|
over = scope[check]
|
8
|
-
scope.error(check) if over && scope.value&.public_send(operation, over)
|
12
|
+
scope.error(check, fail_on: "#{operation} #{over}") if over && scope.value&.public_send(operation, over)
|
9
13
|
end
|
10
14
|
|
11
15
|
def at_size(scope, check, operation)
|
12
16
|
over = scope[check]
|
13
|
-
scope.error(check) if over && scope.value&.size&.public_send(operation, over)
|
17
|
+
scope.error(check, fail_on: "#{operation} #{over}") if over && scope.value&.size&.public_send(operation, over)
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
20
|
+
def required_keys(scope)
|
17
21
|
required = scope[:required]
|
18
|
-
return unless required
|
22
|
+
return unless required.is_a?(Array)
|
19
23
|
|
20
24
|
missing_keys = required - scope.value.keys
|
21
25
|
scope.error(:required, missing_keys: missing_keys) if missing_keys.any?
|
@@ -36,6 +40,14 @@ module SimpleJSONSchema
|
|
36
40
|
|
37
41
|
scope.error(:const) if scope.key?(:const) && scope[:const] != scope.value
|
38
42
|
end
|
43
|
+
|
44
|
+
def json_pointer?(value)
|
45
|
+
JSON_POINTER_REGEX.match?(value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def relative_json_pointer?(value)
|
49
|
+
RELATIVE_JSON_POINTER_REGEX.match?(value)
|
50
|
+
end
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module SimpleJSONSchema
|
4
4
|
module Concerns
|
5
5
|
module HashAccessor
|
6
|
-
def hash_accessor(hash_name,
|
6
|
+
def hash_accessor(hash_name, accessors)
|
7
7
|
define_method(hash_name) do
|
8
8
|
instance_variable_get("@#{hash_name}") ||
|
9
9
|
instance_variable_set("@#{hash_name}", {})
|
@@ -4,11 +4,25 @@ module SimpleJSONSchema
|
|
4
4
|
module PropertiesHelper
|
5
5
|
class << self
|
6
6
|
def checkers(scope)
|
7
|
-
Checker.
|
7
|
+
Checker.required_keys(scope)
|
8
8
|
Checker.at_size(scope, :maxProperties, :>)
|
9
9
|
Checker.at_size(scope, :minProperties, :<)
|
10
10
|
end
|
11
11
|
|
12
|
+
def each_dependency(scope)
|
13
|
+
dependencies = scope[:dependencies]
|
14
|
+
return unless dependencies.is_a?(Hash)
|
15
|
+
|
16
|
+
value = scope.value
|
17
|
+
return unless value.is_a?(Hash)
|
18
|
+
|
19
|
+
dependencies.each_key do |dependency|
|
20
|
+
next unless value.key?(dependency)
|
21
|
+
|
22
|
+
yield([:dependencies, dependency])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
12
26
|
def processe_defualt(scope)
|
13
27
|
return unless scope.options[:insert_defaults] == true
|
14
28
|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleJSONSchema
|
4
|
+
module RefHelper
|
5
|
+
INTEGER_REGEX = /\A-?\d+\Z/.freeze
|
6
|
+
POINTER_SPLIT = %r{(?<!\^)/}.freeze
|
7
|
+
POINTER_GSUB = %r{\^[/^]|~[01]}.freeze
|
8
|
+
POINTER_ESC = { '^/' => '/', '^^' => '^', '~0' => '~', '~1' => '/' }.freeze
|
9
|
+
RefPointer = Struct.new(:ref_paths, :segment, :segment_paths, :parent_uri, keyword_init: true)
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def pointer(scope)
|
13
|
+
ref = scope[:$ref]
|
14
|
+
return nil if ref.nil?
|
15
|
+
|
16
|
+
if ref.start_with?('#')
|
17
|
+
local_ref(scope, ref[1..])
|
18
|
+
else
|
19
|
+
ref_uri = URIExtender.join_uri(scope.parent_uri, ref)
|
20
|
+
if (id = scope.loaded_ids[ref_uri.to_s])
|
21
|
+
return RefPointer.new(ref_paths: id[:schema_paths], segment: id[:schema], parent_uri: ref_uri)
|
22
|
+
end
|
23
|
+
|
24
|
+
uri_ref(scope, ref_uri)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def local_ref(scope, ref)
|
31
|
+
return RefPointer.new unless Checker.json_pointer?(ref)
|
32
|
+
|
33
|
+
paths, parent_uri = path_of_ref(scope.schema, ref)
|
34
|
+
RefPointer.new(ref_paths: paths, parent_uri: parent_uri || scope.parent_uri)
|
35
|
+
end
|
36
|
+
|
37
|
+
def uri_ref(scope, ref_uri)
|
38
|
+
segment = resolver_uri(scope, ref_uri)
|
39
|
+
reref_base(segment, scope.schema_paths)
|
40
|
+
segment_paths, parent_uri = path_of_ref(segment, ref_uri.fragment) if Checker.json_pointer?(ref_uri.fragment)
|
41
|
+
|
42
|
+
RefPointer.new(ref_paths: scope.schema_paths, segment: segment,
|
43
|
+
segment_paths: segment_paths || [], parent_uri: parent_uri || ref_uri)
|
44
|
+
end
|
45
|
+
|
46
|
+
def resolver_uri(scope, uri)
|
47
|
+
schema = scope.cache.fetch(uri.to_s) do
|
48
|
+
if (resolver = scope.options[:resolver]) && resolver.respond_to?(:call)
|
49
|
+
resolver.call(uri)
|
50
|
+
else
|
51
|
+
JSON.parse(::Net::HTTP.get(uri))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
schema.is_a?(Hash) ? schema.with_indifferent_access : schema
|
56
|
+
end
|
57
|
+
|
58
|
+
def path_of_ref(schema, ref)
|
59
|
+
paths = decoded_ref(ref)
|
60
|
+
parent_uri = pointer_uri(schema, paths)
|
61
|
+
[paths, parent_uri]
|
62
|
+
end
|
63
|
+
|
64
|
+
def decoded_ref(pointer)
|
65
|
+
URI.decode_www_form_component(pointer).split(POINTER_SPLIT).map do |part|
|
66
|
+
if INTEGER_REGEX.match?(part)
|
67
|
+
part.to_i
|
68
|
+
else
|
69
|
+
part.gsub(POINTER_GSUB) { |m| POINTER_ESC[m] }
|
70
|
+
end
|
71
|
+
end.reject(&:blank?)
|
72
|
+
end
|
73
|
+
|
74
|
+
def pointer_uri(schema, paths)
|
75
|
+
uri_parts = nil
|
76
|
+
|
77
|
+
paths.reduce(schema) do |obj, token|
|
78
|
+
next obj.fetch(token.to_i) if obj.is_a?(Array)
|
79
|
+
|
80
|
+
if (obj_id = obj[:$id])
|
81
|
+
uri_parts ||= []
|
82
|
+
uri_parts << obj_id
|
83
|
+
end
|
84
|
+
obj.fetch(token)
|
85
|
+
end
|
86
|
+
uri_parts ? URI.join(*uri_parts) : nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def reref_base(schema, paths)
|
90
|
+
return if schema.nil? || paths.empty?
|
91
|
+
|
92
|
+
nested_ref_replace_value(schema) do
|
93
|
+
"#/#{paths.join('/')}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def nested_ref_replace_value(object, &block)
|
98
|
+
if object.respond_to?(:key?) && object.key?(:$ref) && object[:$ref].start_with?('#')
|
99
|
+
object[:$ref] = yield()
|
100
|
+
elsif object.respond_to?(:each)
|
101
|
+
r = nil
|
102
|
+
object.find { |*a| r = nested_ref_replace_value(a.last, &block) }
|
103
|
+
r
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -13,7 +13,7 @@ module SimpleJSONSchema
|
|
13
13
|
String => 'string'
|
14
14
|
}.freeze
|
15
15
|
|
16
|
-
hash_accessor :scope,
|
16
|
+
hash_accessor :scope, %i[data schema type draft data_paths schema_paths errors parent_uri ids options]
|
17
17
|
|
18
18
|
def initialize(**args)
|
19
19
|
scope.merge!(args)
|
@@ -21,15 +21,25 @@ module SimpleJSONSchema
|
|
21
21
|
self.data_paths ||= []
|
22
22
|
self.schema_paths ||= []
|
23
23
|
self.errors ||= []
|
24
|
+
self.ids ||= {}
|
24
25
|
self.options ||= {}
|
25
26
|
self.type ||= evaluate_type
|
26
27
|
end
|
27
28
|
|
28
29
|
def path_to(data_path: nil, schema_path: nil, type: nil)
|
30
|
+
return self if data_path.nil? && schema_path.nil? && type.nil?
|
31
|
+
|
29
32
|
new_data_paths = data_paths + [data_path].flatten.compact
|
30
33
|
new_schema_paths = schema_paths + [schema_path].flatten.compact
|
31
34
|
|
32
|
-
|
35
|
+
merge(data_paths: new_data_paths, schema_paths: new_schema_paths, type: type)
|
36
|
+
end
|
37
|
+
|
38
|
+
def merge(data_paths: self.data_paths, schema_paths: self.schema_paths, type: nil, parent_uri: nil)
|
39
|
+
self.class.new(scope.merge(data_paths: data_paths,
|
40
|
+
schema_paths: schema_paths,
|
41
|
+
type: type,
|
42
|
+
parent_uri: parent_uri || URIExtender.join_uri(self.parent_uri, id)))
|
33
43
|
end
|
34
44
|
|
35
45
|
def replace_data(new_data)
|
@@ -53,6 +63,11 @@ module SimpleJSONSchema
|
|
53
63
|
errors.push(error)
|
54
64
|
end
|
55
65
|
|
66
|
+
def only_cache
|
67
|
+
self.options = { cache: cache }
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
56
71
|
def value
|
57
72
|
dig(data, data_paths)
|
58
73
|
end
|
@@ -60,27 +75,15 @@ module SimpleJSONSchema
|
|
60
75
|
def value=(new_value)
|
61
76
|
return if errors.any? # only convert value until be invalid.
|
62
77
|
|
63
|
-
|
64
|
-
|
65
|
-
if steps.empty?
|
66
|
-
data[leaf] = new_value
|
67
|
-
else
|
68
|
-
data.dig(*steps)[leaf] = new_value
|
69
|
-
end
|
78
|
+
replace(data, data_paths, new_value) { self.data = new_value }
|
70
79
|
end
|
71
80
|
|
72
81
|
def segment
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
def [](key)
|
77
|
-
return unless segment.is_a?(Hash)
|
78
|
-
|
79
|
-
segment[key]
|
82
|
+
dig(schema, schema_paths)
|
80
83
|
end
|
81
84
|
|
82
|
-
def
|
83
|
-
|
85
|
+
def segment=(new_segment)
|
86
|
+
replace(schema, schema_paths, new_segment) { self.schema = new_segment }
|
84
87
|
end
|
85
88
|
|
86
89
|
def segment?
|
@@ -92,8 +95,22 @@ module SimpleJSONSchema
|
|
92
95
|
!(segment == true || segment.nil?)
|
93
96
|
end
|
94
97
|
|
98
|
+
def id
|
99
|
+
self[:$id]
|
100
|
+
end
|
101
|
+
|
102
|
+
def [](key)
|
103
|
+
return unless segment.is_a?(Hash)
|
104
|
+
|
105
|
+
segment[key]
|
106
|
+
end
|
107
|
+
|
108
|
+
def key?(key)
|
109
|
+
segment.is_a?(Hash) && segment.key?(key)
|
110
|
+
end
|
111
|
+
|
95
112
|
def cache
|
96
|
-
options[:cache] ||=
|
113
|
+
options[:cache] ||= Cache.new
|
97
114
|
end
|
98
115
|
|
99
116
|
def around_hooks
|
@@ -102,11 +119,19 @@ module SimpleJSONSchema
|
|
102
119
|
options[:after_property_validation]&.call(self)
|
103
120
|
end
|
104
121
|
|
122
|
+
def loaded_ids
|
123
|
+
if ids.empty?
|
124
|
+
resolve_ids(ids, schema)
|
125
|
+
ids[:$loaded] = true
|
126
|
+
end
|
127
|
+
ids
|
128
|
+
end
|
129
|
+
|
105
130
|
private
|
106
131
|
|
107
132
|
def evaluate_type
|
108
133
|
if key?(:type)
|
109
|
-
|
134
|
+
self[:type]
|
110
135
|
else
|
111
136
|
CLASS_TYPE_TRANSLATE[value.class]
|
112
137
|
end
|
@@ -119,5 +144,34 @@ module SimpleJSONSchema
|
|
119
144
|
rescue TypeError
|
120
145
|
nil
|
121
146
|
end
|
147
|
+
|
148
|
+
def replace(hash, paths, value)
|
149
|
+
*steps, leaf = paths
|
150
|
+
|
151
|
+
if steps.empty?
|
152
|
+
if leaf.nil?
|
153
|
+
yield if block_given?
|
154
|
+
else
|
155
|
+
hash[leaf] = value
|
156
|
+
end
|
157
|
+
else
|
158
|
+
hash.dig(*steps)[leaf] = value
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def resolve_ids(ids, schema, parent_uri = nil, schema_paths = [])
|
163
|
+
case schema
|
164
|
+
when Array
|
165
|
+
schema.each_with_index { |subschema, index| resolve_ids(ids, subschema, parent_uri, schema_paths + [index]) }
|
166
|
+
when Hash
|
167
|
+
uri = URIExtender.join_uri(parent_uri, schema[:$id])
|
168
|
+
|
169
|
+
schema.each do |key, value|
|
170
|
+
ids[uri.to_s] = { schema: schema, schema_paths: schema_paths } if key == '$id' && uri != parent_uri
|
171
|
+
|
172
|
+
resolve_ids(ids, value, uri, schema_paths + [key])
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
122
176
|
end
|
123
177
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SimpleJSONSchema
|
4
|
+
module URIExtender
|
5
|
+
class << self
|
6
|
+
def join_uri(base, complement)
|
7
|
+
complement = URI.parse(complement) if complement
|
8
|
+
|
9
|
+
if base && complement
|
10
|
+
return complement if base.relative? && complement.relative?
|
11
|
+
|
12
|
+
URI.join(base, complement)
|
13
|
+
else
|
14
|
+
complement || base
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -13,10 +13,86 @@ module SimpleJSONSchema
|
|
13
13
|
class << self
|
14
14
|
def validate(scope)
|
15
15
|
return unless scope.segment?
|
16
|
+
return if validate_ref(scope)
|
16
17
|
|
17
18
|
Checker.enum(scope)
|
18
19
|
Checker.const(scope)
|
19
20
|
|
21
|
+
validate_correlations(scope)
|
22
|
+
validate_by_type(scope)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def validate?(scope)
|
28
|
+
scope.errors = []
|
29
|
+
|
30
|
+
validate(scope.only_cache)
|
31
|
+
scope.errors.none?
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_ref(scope)
|
35
|
+
ref_pointer = RefHelper.pointer(scope)
|
36
|
+
return if ref_pointer.nil?
|
37
|
+
|
38
|
+
new_scope = scope.merge(schema_paths: ref_pointer.ref_paths, parent_uri: ref_pointer.parent_uri)
|
39
|
+
new_scope.segment = ref_pointer.segment unless ref_pointer.segment.nil?
|
40
|
+
validate(new_scope.path_to(schema_path: ref_pointer.segment_paths))
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_correlations(scope)
|
45
|
+
validate_all_of(scope)
|
46
|
+
validate_any_of(scope)
|
47
|
+
validate_one_of(scope)
|
48
|
+
validate_not(scope)
|
49
|
+
validate_if_then_else(scope)
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_all_of(scope)
|
53
|
+
scope[:allOf]&.each_index do |index|
|
54
|
+
validate(scope.path_to(schema_path: [:allOf, index]).only_cache)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_any_of(scope)
|
59
|
+
any_of = scope[:anyOf]
|
60
|
+
return if any_of.nil?
|
61
|
+
return if any_of.each_index.any? { |index| validate?(scope.path_to(schema_path: [:anyOf, index])) }
|
62
|
+
|
63
|
+
any_of.each_index { |index| validate(scope.path_to(schema_path: [:anyOf, index]).only_cache) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_one_of(scope)
|
67
|
+
one_of = scope[:oneOf]
|
68
|
+
return if one_of.nil?
|
69
|
+
|
70
|
+
valid_count = one_of.each_index.count { |index| validate?(scope.path_to(schema_path: [:oneOf, index])) }
|
71
|
+
|
72
|
+
if valid_count > 1
|
73
|
+
scope.error(:oneOf)
|
74
|
+
elsif valid_count.zero?
|
75
|
+
one_of.each_index { |index| validate(scope.path_to(schema_path: [:oneOf, index]).only_cache) }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate_not(scope)
|
80
|
+
return unless scope.key?(:not)
|
81
|
+
|
82
|
+
scope.error(:not) if validate?(scope.path_to(schema_path: :not))
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_if_then_else(scope)
|
86
|
+
return unless scope.key?(:if)
|
87
|
+
|
88
|
+
if validate?(scope.path_to(schema_path: :if))
|
89
|
+
validate(scope.path_to(schema_path: :then)) if scope.key?(:then)
|
90
|
+
elsif scope.key?(:else)
|
91
|
+
validate(scope.path_to(schema_path: :else))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_by_type(scope)
|
20
96
|
case scope.type
|
21
97
|
when 'object'
|
22
98
|
valid_object(scope)
|
@@ -29,33 +105,37 @@ module SimpleJSONSchema
|
|
29
105
|
end
|
30
106
|
end
|
31
107
|
|
32
|
-
private
|
33
|
-
|
34
|
-
def validate?(scope)
|
35
|
-
scope.errors = []
|
36
|
-
scope.options = { cache: scope.cache }
|
37
|
-
|
38
|
-
validate(scope)
|
39
|
-
scope.errors.none?
|
40
|
-
end
|
41
|
-
|
42
108
|
def validate_base_types(scope)
|
43
109
|
VALIDATORES[scope.type]&.valid(scope)
|
44
110
|
end
|
45
111
|
|
46
112
|
def valid_object(scope)
|
47
|
-
|
48
|
-
|
49
|
-
return scope.error(:object) unless value.is_a?(Hash)
|
113
|
+
return scope.error(:object) unless scope.value.is_a?(Hash)
|
50
114
|
|
51
115
|
PropertiesHelper.processe_defualt(scope)
|
52
116
|
PropertiesHelper.checkers(scope)
|
53
117
|
|
118
|
+
valid_object_dependencies(scope)
|
119
|
+
valid_object_property_names(scope)
|
120
|
+
valid_object_properties(scope)
|
121
|
+
end
|
122
|
+
|
123
|
+
def valid_object_dependencies(scope)
|
124
|
+
PropertiesHelper.each_dependency(scope) do |schema_path|
|
125
|
+
new_scope = scope.path_to(schema_path: schema_path)
|
126
|
+
new_scope.segment = { required: new_scope.segment } if new_scope.segment.is_a?(Array)
|
127
|
+
validate(new_scope)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def valid_object_property_names(scope)
|
54
132
|
PropertiesHelper.each_property_name(scope) do |property_name|
|
55
133
|
validate(scope.path_to(schema_path: :propertyNames).replace_data(property_name))
|
56
134
|
end
|
135
|
+
end
|
57
136
|
|
58
|
-
|
137
|
+
def valid_object_properties(scope)
|
138
|
+
scope.value.each_key do |property_name|
|
59
139
|
PropertiesHelper.map_property_schema_path(scope, property_name).each do |schema_path|
|
60
140
|
new_scope = scope.path_to(schema_path: schema_path, data_path: property_name)
|
61
141
|
new_scope.around_hooks do
|
@@ -8,9 +8,6 @@ module SimpleJSONSchema
|
|
8
8
|
EMAIL_REGEX = /\A[^@\s]+@([\p{L}\d-]+\.)+[\p{L}\d\-]{2,}\z/i.freeze
|
9
9
|
LABEL_REGEX_STRING = '[\p{L}\p{N}]([\p{L}\p{N}\-]*[\p{L}\p{N}])?'
|
10
10
|
HOSTNAME_REGEX = /\A(#{LABEL_REGEX_STRING}\.)*#{LABEL_REGEX_STRING}\z/i.freeze
|
11
|
-
JSON_POINTER_REGEX_STRING = '(\/([^~\/]|~[01])*)*'
|
12
|
-
JSON_POINTER_REGEX = /\A#{JSON_POINTER_REGEX_STRING}\z/.freeze
|
13
|
-
RELATIVE_JSON_POINTER_REGEX = /\A(0|[1-9]\d*)(#|#{JSON_POINTER_REGEX_STRING})?\z/.freeze
|
14
11
|
DATE_TIME_OFFSET_REGEX = /(Z|[+\-]([01][0-9]|2[0-3]):[0-5][0-9])\z/i.freeze
|
15
12
|
INVALID_QUERY_REGEX = /[[:space:]]/.freeze
|
16
13
|
ASCII_REGEX = /[^[:ascii:]]/.freeze
|
@@ -57,9 +54,9 @@ module SimpleJSONSchema
|
|
57
54
|
# when 'uri-template'
|
58
55
|
# valid_uri_template?(value)
|
59
56
|
when 'json-pointer'
|
60
|
-
|
57
|
+
Checker.json_pointer?(value)
|
61
58
|
when 'relative-json-pointer'
|
62
|
-
|
59
|
+
Checker.relative_json_pointer?(value)
|
63
60
|
when 'regex'
|
64
61
|
EcmaReValidator.valid?(value)
|
65
62
|
end
|
@@ -9,6 +9,7 @@ module SimpleJSONSchema
|
|
9
9
|
value = scope.value
|
10
10
|
|
11
11
|
return scope.error(:string) unless value.is_a?(::String)
|
12
|
+
return scope.error(:blank) if scope[:required] == true && value.blank?
|
12
13
|
|
13
14
|
Checker.at_size(scope, :maxLength, :>)
|
14
15
|
Checker.at_size(scope, :minLength, :<)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_json_schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Georgeo Rocco
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -187,13 +187,17 @@ files:
|
|
187
187
|
- Rakefile
|
188
188
|
- bin/console
|
189
189
|
- bin/setup
|
190
|
+
- bin/simple_json_schema
|
190
191
|
- lib/simple_json_schema.rb
|
192
|
+
- lib/simple_json_schema/cache.rb
|
191
193
|
- lib/simple_json_schema/checker.rb
|
192
194
|
- lib/simple_json_schema/concerns/hash_acessor.rb
|
193
195
|
- lib/simple_json_schema/items_helper.rb
|
194
196
|
- lib/simple_json_schema/properties_helper.rb
|
197
|
+
- lib/simple_json_schema/ref_helper.rb
|
195
198
|
- lib/simple_json_schema/regex_helper.rb
|
196
199
|
- lib/simple_json_schema/scope.rb
|
200
|
+
- lib/simple_json_schema/uri_extender.rb
|
197
201
|
- lib/simple_json_schema/validator.rb
|
198
202
|
- lib/simple_json_schema/validators/base.rb
|
199
203
|
- lib/simple_json_schema/validators/boolean.rb
|