json_schemer 0.1.1 → 0.1.2
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/Gemfile.lock +1 -1
- data/README.md +35 -3
- data/lib/json_schemer.rb +65 -49
- data/lib/json_schemer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8a7a9d5181f0da2becb05779a587291aaa9fdcdf1ce2eeb2745165f860ff4c4
|
4
|
+
data.tar.gz: a287a3ce5b40ad941b114e4c95c4ad613c3372b3aa30549078ce998b9405c913
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb6bb847b36e285d969c160462d0a42d3fb0ba1cce7f479f13b6bfe759df299591f86bb05d1f6a6e545a96508c27fb1cb48e828ec431e07c3b8036392dbc20c0
|
7
|
+
data.tar.gz: 53a14606a501034d0693f54e2dd56706a573d950c26fddc9950effcc9dbc4762eaf929756b1d609a9e7bf0c0a5507dd8913e5c6078fbf0ff5b68eae7b851a6e9
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -24,15 +24,47 @@ Or install it yourself as:
|
|
24
24
|
require 'json_schemer'
|
25
25
|
|
26
26
|
schema = {
|
27
|
-
'type' => '
|
27
|
+
'type' => 'object',
|
28
|
+
'properties' => {
|
29
|
+
'abc' => {
|
30
|
+
'type' => 'integer',
|
31
|
+
'minimum' => 11
|
32
|
+
}
|
33
|
+
}
|
28
34
|
}
|
29
35
|
schemer = JSONSchemer::Schema.new(schema)
|
30
36
|
|
31
|
-
|
37
|
+
# true/false validation
|
38
|
+
|
39
|
+
schemer.valid?({ 'abc' => 11 })
|
32
40
|
# => true
|
33
41
|
|
34
|
-
schemer.valid?(
|
42
|
+
schemer.valid?({ 'abc' => 10 })
|
35
43
|
# => false
|
44
|
+
|
45
|
+
# error validation (`validate` returns an enumerator)
|
46
|
+
|
47
|
+
schemer.validate({ 'abc' => 10 }).to_a
|
48
|
+
# => [{"data"=>10, "schema"=>{"type"=>"integer", "minimum"=>11}, "pointer"=>"#/abc", "type"=>"minimum"}]
|
49
|
+
```
|
50
|
+
|
51
|
+
## Options
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
JSONSchemer::Schema.new(
|
55
|
+
schema,
|
56
|
+
|
57
|
+
# validate `format` (https://tools.ietf.org/html/draft-handrews-json-schema-validation-00#section-7)
|
58
|
+
# true/false
|
59
|
+
# default: true
|
60
|
+
format: true,
|
61
|
+
|
62
|
+
# resolve external references
|
63
|
+
# 'net/http'/proc/lambda/respond_to?(:call)
|
64
|
+
# 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }
|
65
|
+
# default: proc { |uri| raise UnknownRef, uri.to_s }
|
66
|
+
ref_resolver: 'net/http'
|
67
|
+
)
|
36
68
|
```
|
37
69
|
|
38
70
|
## Development
|
data/lib/json_schemer.rb
CHANGED
@@ -15,17 +15,29 @@ require "uri_template"
|
|
15
15
|
|
16
16
|
module JSONSchemer
|
17
17
|
class Schema
|
18
|
+
class InvalidMetaSchema < StandardError; end
|
19
|
+
class UnknownRef < StandardError; end
|
20
|
+
|
21
|
+
META_SCHEMA = 'http://json-schema.org/draft-07/schema#'
|
22
|
+
DEFAULT_REF_RESOLVER = proc { |uri| raise UnknownRef, uri.to_s }.freeze
|
23
|
+
NET_HTTP_REF_RESOLVER = proc { |uri| JSON.parse(Net::HTTP.get(uri)) }.freeze
|
18
24
|
BOOLEANS = Set[true, false].freeze
|
19
25
|
|
20
|
-
def initialize(schema)
|
26
|
+
def initialize(schema, format: true, ref_resolver: DEFAULT_REF_RESOLVER)
|
27
|
+
if schema.is_a?(Hash) && schema.key?('$schema') && schema['$schema'] != META_SCHEMA
|
28
|
+
raise InvalidMetaSchema, "draft-07 is the only supported meta-schema (#{META_SCHEMA})"
|
29
|
+
end
|
30
|
+
|
21
31
|
@root = schema
|
32
|
+
@format = format
|
33
|
+
@ref_resolver = ref_resolver == 'net/http' ? NET_HTTP_REF_RESOLVER : ref_resolver
|
22
34
|
end
|
23
35
|
|
24
|
-
def valid?(data, schema = root, pointer = '
|
36
|
+
def valid?(data, schema = root, pointer = '', parent_uri = nil)
|
25
37
|
validate(data, schema, pointer, parent_uri).none?
|
26
38
|
end
|
27
39
|
|
28
|
-
def validate(data, schema = root, pointer = '
|
40
|
+
def validate(data, schema = root, pointer = '', parent_uri = nil)
|
29
41
|
return enum_for(:validate, data, schema, pointer, parent_uri) unless block_given?
|
30
42
|
|
31
43
|
return if schema == true
|
@@ -45,6 +57,7 @@ module JSONSchemer
|
|
45
57
|
if_schema = schema['if']
|
46
58
|
then_schema = schema['then']
|
47
59
|
else_schema = schema['else']
|
60
|
+
format = schema['format']
|
48
61
|
ref = schema['$ref']
|
49
62
|
id = schema['$id']
|
50
63
|
|
@@ -55,6 +68,8 @@ module JSONSchemer
|
|
55
68
|
return
|
56
69
|
end
|
57
70
|
|
71
|
+
validate_format(data, schema, pointer, format, &Proc.new) if format && format?
|
72
|
+
|
58
73
|
yield error(data, schema, pointer, 'enum') if enum && !enum.include?(data)
|
59
74
|
yield error(data, schema, pointer, 'const') if schema.key?('const') && schema['const'] != data
|
60
75
|
|
@@ -91,7 +106,11 @@ module JSONSchemer
|
|
91
106
|
|
92
107
|
private
|
93
108
|
|
94
|
-
attr_reader :root
|
109
|
+
attr_reader :root, :ref_resolver
|
110
|
+
|
111
|
+
def format?
|
112
|
+
!!@format
|
113
|
+
end
|
95
114
|
|
96
115
|
def error(data, schema, pointer, type)
|
97
116
|
{
|
@@ -144,19 +163,59 @@ module JSONSchemer
|
|
144
163
|
if ref.start_with?('#')
|
145
164
|
validate(data, ref_pointer.eval(root), pointer, pointer_uri(root, ref_pointer), &Proc.new)
|
146
165
|
else
|
147
|
-
ref_root =
|
166
|
+
ref_root = ref_resolver.call(ref_uri)
|
148
167
|
ref_object = self.class.new(ref_root)
|
149
168
|
ref_object.validate(data, ref_pointer.eval(ref_root), pointer, pointer_uri(ref_root, ref_pointer), &Proc.new)
|
150
169
|
end
|
151
170
|
elsif ids.key?(ref_uri.to_s)
|
152
171
|
validate(data, ids.fetch(ref_uri.to_s), pointer, ref_uri, &Proc.new)
|
153
172
|
else
|
154
|
-
ref_root =
|
173
|
+
ref_root = ref_resolver.call(ref_uri)
|
155
174
|
ref_object = self.class.new(ref_root)
|
156
175
|
ref_object.validate(data, ref_object.ids.fetch(ref_uri.to_s, ref_root), pointer, ref_uri, &Proc.new)
|
157
176
|
end
|
158
177
|
end
|
159
178
|
|
179
|
+
def validate_format(data, schema, pointer, format)
|
180
|
+
valid = case format
|
181
|
+
when 'date-time'
|
182
|
+
valid_date_time?(data)
|
183
|
+
when 'date'
|
184
|
+
valid_date_time?("#{data}T04:05:06.123456789+07:00")
|
185
|
+
when 'time'
|
186
|
+
valid_date_time?("2001-02-03T#{data}")
|
187
|
+
when 'email'
|
188
|
+
data.ascii_only? && valid_email?(data)
|
189
|
+
when 'idn-email'
|
190
|
+
valid_email?(data)
|
191
|
+
when 'hostname'
|
192
|
+
data.ascii_only? && valid_hostname?(data)
|
193
|
+
when 'idn-hostname'
|
194
|
+
valid_hostname?(data)
|
195
|
+
when 'ipv4'
|
196
|
+
valid_ip?(data, :v4)
|
197
|
+
when 'ipv6'
|
198
|
+
valid_ip?(data, :v6)
|
199
|
+
when 'uri'
|
200
|
+
data.ascii_only? && valid_iri?(data)
|
201
|
+
when 'uri-reference'
|
202
|
+
data.ascii_only? && (valid_iri?(data) || valid_iri_reference?(data))
|
203
|
+
when 'iri'
|
204
|
+
valid_iri?(data)
|
205
|
+
when 'iri-reference'
|
206
|
+
valid_iri?(data) || valid_iri_reference?(data)
|
207
|
+
when 'uri-template'
|
208
|
+
valid_uri_template?(data)
|
209
|
+
when 'json-pointer'
|
210
|
+
valid_json_pointer?(data)
|
211
|
+
when 'relative-json-pointer'
|
212
|
+
valid_relative_json_pointer?(data)
|
213
|
+
when 'regex'
|
214
|
+
EcmaReValidator.valid?(data)
|
215
|
+
end
|
216
|
+
yield error(data, schema, pointer, 'format') unless valid
|
217
|
+
end
|
218
|
+
|
160
219
|
def validate_numeric(data, schema, pointer)
|
161
220
|
multiple_of = schema['multipleOf']
|
162
221
|
maximum = schema['maximum']
|
@@ -202,7 +261,6 @@ module JSONSchemer
|
|
202
261
|
max_length = schema['maxLength']
|
203
262
|
min_length = schema['minLength']
|
204
263
|
pattern = schema['pattern']
|
205
|
-
format = schema['format']
|
206
264
|
content_encoding = schema['contentEncoding']
|
207
265
|
content_media_type = schema['contentMediaType']
|
208
266
|
|
@@ -210,8 +268,6 @@ module JSONSchemer
|
|
210
268
|
yield error(data, schema, pointer, 'minLength') if min_length && data.size < min_length
|
211
269
|
yield error(data, schema, pointer, 'pattern') if pattern && Regexp.new(pattern) !~ data
|
212
270
|
|
213
|
-
validate_string_format(data, schema, pointer, format, &Proc.new) if format
|
214
|
-
|
215
271
|
if content_encoding || content_media_type
|
216
272
|
decoded_data = data
|
217
273
|
|
@@ -236,46 +292,6 @@ module JSONSchemer
|
|
236
292
|
end
|
237
293
|
end
|
238
294
|
|
239
|
-
def validate_string_format(data, schema, pointer, format)
|
240
|
-
valid = case format
|
241
|
-
when 'date-time'
|
242
|
-
valid_date_time?(data)
|
243
|
-
when 'date'
|
244
|
-
valid_date_time?("#{data}T04:05:06.123456789+07:00")
|
245
|
-
when 'time'
|
246
|
-
valid_date_time?("2001-02-03T#{data}")
|
247
|
-
when 'email'
|
248
|
-
data.ascii_only? && valid_email?(data)
|
249
|
-
when 'idn-email'
|
250
|
-
valid_email?(data)
|
251
|
-
when 'hostname'
|
252
|
-
data.ascii_only? && valid_hostname?(data)
|
253
|
-
when 'idn-hostname'
|
254
|
-
valid_hostname?(data)
|
255
|
-
when 'ipv4'
|
256
|
-
valid_ip?(data, :v4)
|
257
|
-
when 'ipv6'
|
258
|
-
valid_ip?(data, :v6)
|
259
|
-
when 'uri'
|
260
|
-
data.ascii_only? && valid_iri?(data)
|
261
|
-
when 'uri-reference'
|
262
|
-
data.ascii_only? && (valid_iri?(data) || valid_iri_reference?(data))
|
263
|
-
when 'iri'
|
264
|
-
valid_iri?(data)
|
265
|
-
when 'iri-reference'
|
266
|
-
valid_iri?(data) || valid_iri_reference?(data)
|
267
|
-
when 'uri-template'
|
268
|
-
valid_uri_template?(data)
|
269
|
-
when 'json-pointer'
|
270
|
-
valid_json_pointer?(data)
|
271
|
-
when 'relative-json-pointer'
|
272
|
-
valid_relative_json_pointer?(data)
|
273
|
-
when 'regex'
|
274
|
-
EcmaReValidator.valid?(data)
|
275
|
-
end
|
276
|
-
yield error(data, schema, pointer, 'format') unless valid
|
277
|
-
end
|
278
|
-
|
279
295
|
def validate_array(data, schema, pointer, parent_uri, &block)
|
280
296
|
unless data.is_a?(Array)
|
281
297
|
yield error(data, schema, pointer, 'array')
|
data/lib/json_schemer/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_schemer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Harsha
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|