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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f44b977f6f07e9dfbb34d58681bc0b22059143bc761364b8c8edb81b5ba7fb16
4
- data.tar.gz: f606d14d205b33bb4f1c221cb6526e79afee01d965d61883763c8f516fabd69e
3
+ metadata.gz: a8a7a9d5181f0da2becb05779a587291aaa9fdcdf1ce2eeb2745165f860ff4c4
4
+ data.tar.gz: a287a3ce5b40ad941b114e4c95c4ad613c3372b3aa30549078ce998b9405c913
5
5
  SHA512:
6
- metadata.gz: 046d14ee062722084b3b7954c488b6e86ba89b5ba112879b53ecf173c3c969d183ec4baa381c2f30eca61f6595fbe199337cff5ecfbb4eb7226d1f662d4b80e9
7
- data.tar.gz: 684807637dc7510c868fc173716a1846c35368db792bd8fa1a8e2de605d3e58901df668b451567610294bd989ea057a6fb28e02bd59c2bd4d1df0b4f7571d629
6
+ metadata.gz: cb6bb847b36e285d969c160462d0a42d3fb0ba1cce7f479f13b6bfe759df299591f86bb05d1f6a6e545a96508c27fb1cb48e828ec431e07c3b8036392dbc20c0
7
+ data.tar.gz: 53a14606a501034d0693f54e2dd56706a573d950c26fddc9950effcc9dbc4762eaf929756b1d609a9e7bf0c0a5507dd8913e5c6078fbf0ff5b68eae7b851a6e9
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json_schemer (0.1.1)
4
+ json_schemer (0.1.2)
5
5
  ecma-re-validator (~> 0.1.2)
6
6
  hana (~> 1.3.3)
7
7
  uri_template (~> 0.7.0)
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' => 'integer'
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
- schemer.valid?(1)
37
+ # true/false validation
38
+
39
+ schemer.valid?({ 'abc' => 11 })
32
40
  # => true
33
41
 
34
- schemer.valid?(1.1)
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
@@ -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 = '#', parent_uri = nil)
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 = '#', parent_uri = nil)
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 = JSON.parse(Net::HTTP.get(ref_uri))
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 = JSON.parse(Net::HTTP.get(ref_uri))
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')
@@ -1,3 +1,3 @@
1
1
  module JSONSchemer
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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.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-24 00:00:00.000000000 Z
11
+ date: 2018-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler