jddf 0.2.0 → 0.2.1
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 +9 -4
- data/lib/jddf.rb +1 -1
- data/lib/jddf/schema.rb +65 -6
- data/lib/jddf/validator.rb +49 -3
- data/lib/jddf/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: c72fdc3f849585ccb396ce421b3a786ac80b82e6bd655687663f990324422f65
|
4
|
+
data.tar.gz: 4569216d22965df94997de1934c3e978b558f566607d62e6175102871f1338a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bc424c05db14b6a242b7d4d0c1e407f1fb20b5667724eaff7c97c9f971f07a0aa332c85faa7badc7bbe28fdbb72897eaf0d9cbdde950a331341cfe1c0d11fff
|
7
|
+
data.tar.gz: df9ec4d23c0d91075a386482063b0bc22a1d6722e33b790603a9788d67141aac45d64142b1d0b8bcdcb706a6a2b679dbd30a5b64a523979d8b2b3a67b55a8135
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -31,10 +31,15 @@ gem 'jddf'
|
|
31
31
|
|
32
32
|
The two most important classes offered by the `JDDF` module are:
|
33
33
|
|
34
|
-
* `Schema
|
35
|
-
* `Validator
|
36
|
-
|
37
|
-
|
34
|
+
* [`Schema`][schema], which represents a JDDF schema,
|
35
|
+
* [`Validator`][validator], which can validate a `Schema` against any parsed
|
36
|
+
JSON data, and
|
37
|
+
* [`ValidationError`][validation-error], which represents a single validation
|
38
|
+
problem with the input. `Validator#validate` returns an array of these.
|
39
|
+
|
40
|
+
[schema]: https://www.rubydoc.info/github/jddf/jddf-ruby/master/JDDF/Schema
|
41
|
+
[validator]: https://www.rubydoc.info/github/jddf/jddf-ruby/master/JDDF/Validator
|
42
|
+
[validation-error]: https://www.rubydoc.info/github/jddf/jddf-ruby/master/JDDF/ValidationError
|
38
43
|
|
39
44
|
Here's a working example:
|
40
45
|
|
data/lib/jddf.rb
CHANGED
data/lib/jddf/schema.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JDDF
|
4
|
+
# The keywords that may appear on a JDDF schema.
|
5
|
+
#
|
6
|
+
# Each of these values correspond to an attribute available on {Schema}.
|
4
7
|
SCHEMA_KEYWORDS = %i[
|
5
8
|
definitions
|
6
9
|
ref
|
@@ -14,11 +17,18 @@ module JDDF
|
|
14
17
|
discriminator
|
15
18
|
].freeze
|
16
19
|
|
20
|
+
# The keywords that may appear on a JDDF schema discriminator object.
|
21
|
+
#
|
22
|
+
# Each of these values correspond to an attribute available on
|
23
|
+
# {Discriminator}.
|
17
24
|
DISCRIMINATOR_KEYWORDS = %i[
|
18
25
|
tag
|
19
26
|
mapping
|
20
27
|
].freeze
|
21
28
|
|
29
|
+
# The values the +type+ keyword may take on in a JDDF schema.
|
30
|
+
#
|
31
|
+
# The +type+ attribute of {Schema} has one of these values.
|
22
32
|
TYPES = %i[
|
23
33
|
boolean
|
24
34
|
int8
|
@@ -33,7 +43,28 @@ module JDDF
|
|
33
43
|
timestamp
|
34
44
|
].freeze
|
35
45
|
|
46
|
+
# A JDDF schema.
|
47
|
+
#
|
48
|
+
# This class is a +Struct+. Validate instances against it using
|
49
|
+
# {Validator#validate}.
|
50
|
+
#
|
51
|
+
# This class's attributes are in {SCHEMA_KEYWORDS}.
|
36
52
|
Schema = Struct.new(*SCHEMA_KEYWORDS) do
|
53
|
+
# Construct a {Schema} from parsed JSON.
|
54
|
+
#
|
55
|
+
# This function performs type checks to ensure the data is well-typed, but
|
56
|
+
# does not perform all the checks necesary to ensure data is a correct JDDF
|
57
|
+
# schema. Using this function in combination with {verify} ensures that a
|
58
|
+
# JDDF schema is guaranteed to be correct according to the spec.
|
59
|
+
#
|
60
|
+
# +hash+ should be the result of calling +JSON#parse+.
|
61
|
+
#
|
62
|
+
# @param hash [Hash] a JSON object representing a JDDF schema
|
63
|
+
#
|
64
|
+
# @raise [ArgumentError, TypeError] if the inputted hash is not a valid
|
65
|
+
# schema
|
66
|
+
#
|
67
|
+
# @return [Schema] the parsed schema
|
37
68
|
def self.from_json(hash)
|
38
69
|
raise TypeError.new, 'hash must be a Hash' unless hash.is_a?(Hash)
|
39
70
|
|
@@ -133,6 +164,12 @@ module JDDF
|
|
133
164
|
schema
|
134
165
|
end
|
135
166
|
|
167
|
+
# Determine which of the eight forms this schema takes on.
|
168
|
+
#
|
169
|
+
# This function is well-defined only if the schema is a correct schema --
|
170
|
+
# i.e., you have called {verify} and no errors were raised.
|
171
|
+
#
|
172
|
+
# @return [Symbol] the form of the schema
|
136
173
|
def form
|
137
174
|
return :ref if ref
|
138
175
|
return :type if type
|
@@ -145,7 +182,20 @@ module JDDF
|
|
145
182
|
:empty
|
146
183
|
end
|
147
184
|
|
148
|
-
|
185
|
+
# Check that the schema represents a correct JDDF schema.
|
186
|
+
#
|
187
|
+
# To make it convenient to construct and verify a schema, this function
|
188
|
+
# returns +self+ if the schema is correct.
|
189
|
+
#
|
190
|
+
# @raise [ArgumentError] if the schema is incorrect
|
191
|
+
#
|
192
|
+
# @return [Schema] self
|
193
|
+
def verify(root = self, is_root = true)
|
194
|
+
if definitions
|
195
|
+
raise ArgumentError, 'non-root definitions' unless is_root
|
196
|
+
definitions.values.each { |schema| schema.verify(root, false) }
|
197
|
+
end
|
198
|
+
|
149
199
|
empty = true
|
150
200
|
|
151
201
|
if ref
|
@@ -173,7 +223,7 @@ module JDDF
|
|
173
223
|
|
174
224
|
empty = false
|
175
225
|
|
176
|
-
elements.verify(root)
|
226
|
+
elements.verify(root, false)
|
177
227
|
end
|
178
228
|
|
179
229
|
if properties || optional_properties
|
@@ -181,8 +231,8 @@ module JDDF
|
|
181
231
|
|
182
232
|
empty = false
|
183
233
|
|
184
|
-
properties&.values&.each { |schema| schema.verify(root) }
|
185
|
-
optional_properties&.values&.each { |schema| schema.verify(root) }
|
234
|
+
properties&.values&.each { |schema| schema.verify(root, false) }
|
235
|
+
optional_properties&.values&.each { |schema| schema.verify(root, false) }
|
186
236
|
end
|
187
237
|
|
188
238
|
if values
|
@@ -190,7 +240,7 @@ module JDDF
|
|
190
240
|
|
191
241
|
empty = false
|
192
242
|
|
193
|
-
values.verify(root)
|
243
|
+
values.verify(root, false)
|
194
244
|
end
|
195
245
|
|
196
246
|
if properties && optional_properties
|
@@ -203,7 +253,7 @@ module JDDF
|
|
203
253
|
raise ArgumentError, 'invalid form' unless empty
|
204
254
|
|
205
255
|
discriminator.mapping.values.each do |schema|
|
206
|
-
schema.verify(root)
|
256
|
+
schema.verify(root, false)
|
207
257
|
|
208
258
|
unless schema.form == :properties
|
209
259
|
raise ArgumentError, 'mapping value not of properties form'
|
@@ -220,7 +270,16 @@ module JDDF
|
|
220
270
|
end
|
221
271
|
end
|
222
272
|
|
273
|
+
# A JDDF schema discriminator object.
|
274
|
+
#
|
275
|
+
# This class is a +Struct+. It is primarily a helper sub-structure of
|
276
|
+
# {Schema}.
|
277
|
+
#
|
278
|
+
# The attributes of this struct are in {DISCRIMINATOR_KEYWORDS}.
|
223
279
|
Discriminator = Struct.new(*DISCRIMINATOR_KEYWORDS) do
|
280
|
+
# Construct a {Discriminator} from parsed JSON.
|
281
|
+
#
|
282
|
+
# This is primarily meant to be a helper method to {Schema#from_json}.
|
224
283
|
def self.from_json(hash)
|
225
284
|
raise TypeError, 'tag not String' unless hash['tag'].is_a?(String)
|
226
285
|
raise TypeError, 'mapping not Hash' unless hash['mapping'].is_a?(Hash)
|
data/lib/jddf/validator.rb
CHANGED
@@ -3,17 +3,29 @@
|
|
3
3
|
require 'time'
|
4
4
|
|
5
5
|
module JDDF
|
6
|
-
#
|
6
|
+
# A single JDDF validation error.
|
7
|
+
#
|
8
|
+
# Instances of this class are returned from {Validator#validate}.
|
9
|
+
#
|
10
|
+
# The attributes of this class are both arrays of strings. They represent JSON
|
11
|
+
# Pointers.
|
12
|
+
#
|
13
|
+
# @attr [Array] instance_path an array of strings pointing to the rejected
|
14
|
+
# part of the input ("instance")
|
15
|
+
#
|
16
|
+
# @attr [Array] schema_path an array of strings pointing to the part of the
|
17
|
+
# schema which rejected the instance
|
7
18
|
ValidationError = Struct.new(:instance_path, :schema_path)
|
8
19
|
|
9
|
-
# MaxDepthExceededError
|
20
|
+
# MaxDepthExceededError is raised when the maximum depth of a {Validator} is
|
21
|
+
# exceeded.
|
10
22
|
class MaxDepthExceededError < StandardError
|
11
23
|
def initialize(msg = 'max depth exceeded while validating')
|
12
24
|
super
|
13
25
|
end
|
14
26
|
end
|
15
27
|
|
16
|
-
#
|
28
|
+
# Validates JSON instances against JDDF schemas.
|
17
29
|
class Validator
|
18
30
|
# MaxErrorsError
|
19
31
|
class MaxErrorsError < StandardError
|
@@ -248,9 +260,43 @@ module JDDF
|
|
248
260
|
|
249
261
|
private_constant :VM
|
250
262
|
|
263
|
+
# The maximum stack depth of references to follow when running {validate}.
|
264
|
+
#
|
265
|
+
# If this maximum depth is exceeded, such as if a schema passed to
|
266
|
+
# {validate} is defined cyclically, then {validate} throws a
|
267
|
+
# {MaxDepthExceededError}.
|
268
|
+
#
|
269
|
+
# By default, no maximum depth is enforced. The validator may overflow the
|
270
|
+
# stack if a schema is defined cyclically.
|
271
|
+
#
|
272
|
+
# @return [Integer] the maximum depth of references to follow when validating
|
251
273
|
attr_accessor :max_depth
|
274
|
+
|
275
|
+
# The maximum number of errors to return when running {validate}.
|
276
|
+
#
|
277
|
+
# If this value is set to a number, then it's guaranteed that {validate}
|
278
|
+
# will return an array of size no greater than the value of this attribute.
|
279
|
+
#
|
280
|
+
# By default, no maximum errors is enforced. All validation errors are
|
281
|
+
# returned.
|
282
|
+
#
|
283
|
+
# @return [Integer] the maximum errors to return when validating
|
252
284
|
attr_accessor :max_errors
|
253
285
|
|
286
|
+
# Validate a JDDF schema against a JSON instance.
|
287
|
+
#
|
288
|
+
# The precise rules of validation for this method are defined formally by
|
289
|
+
# the JDDF specification, and this method follows those rules exactly,
|
290
|
+
# assuming that +instance+ is the result of calling +JSON#parse+ using the
|
291
|
+
# standard library's +JSON+ module.
|
292
|
+
#
|
293
|
+
# @param schema [Schema] the schema to validate against
|
294
|
+
#
|
295
|
+
# @param instance [Object] the input ("instance") to validate
|
296
|
+
#
|
297
|
+
# @raise [MaxDepthExceededError} if {max_depth} is exceeded.
|
298
|
+
#
|
299
|
+
# @return [Array] an array of {ValidationError}
|
254
300
|
def validate(schema, instance)
|
255
301
|
vm = VM.new
|
256
302
|
vm.max_depth = max_depth
|
data/lib/jddf/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jddf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ulysse Carion
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|