simple_json_schema 0.1.3 → 0.1.4
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 +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
|
[](https://gitlab.com/vliper/simple_json_schema/-/commits/master)
|
5
5
|
[](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
|