json-schema-ouidou 2.9.0

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +19 -0
  3. data/README.md +496 -0
  4. data/lib/json-schema/attribute.rb +57 -0
  5. data/lib/json-schema/attributes/additionalitems.rb +28 -0
  6. data/lib/json-schema/attributes/additionalproperties.rb +58 -0
  7. data/lib/json-schema/attributes/allof.rb +39 -0
  8. data/lib/json-schema/attributes/anyof.rb +47 -0
  9. data/lib/json-schema/attributes/dependencies.rb +38 -0
  10. data/lib/json-schema/attributes/dependencies_v4.rb +11 -0
  11. data/lib/json-schema/attributes/disallow.rb +12 -0
  12. data/lib/json-schema/attributes/divisibleby.rb +22 -0
  13. data/lib/json-schema/attributes/enum.rb +24 -0
  14. data/lib/json-schema/attributes/extends.rb +48 -0
  15. data/lib/json-schema/attributes/format.rb +14 -0
  16. data/lib/json-schema/attributes/formats/custom.rb +21 -0
  17. data/lib/json-schema/attributes/formats/date.rb +25 -0
  18. data/lib/json-schema/attributes/formats/date_time.rb +34 -0
  19. data/lib/json-schema/attributes/formats/date_time_v4.rb +15 -0
  20. data/lib/json-schema/attributes/formats/ip.rb +41 -0
  21. data/lib/json-schema/attributes/formats/time.rb +22 -0
  22. data/lib/json-schema/attributes/formats/uri.rb +18 -0
  23. data/lib/json-schema/attributes/items.rb +27 -0
  24. data/lib/json-schema/attributes/limit.rb +52 -0
  25. data/lib/json-schema/attributes/limits/items.rb +15 -0
  26. data/lib/json-schema/attributes/limits/length.rb +15 -0
  27. data/lib/json-schema/attributes/limits/max_items.rb +15 -0
  28. data/lib/json-schema/attributes/limits/max_length.rb +15 -0
  29. data/lib/json-schema/attributes/limits/max_properties.rb +15 -0
  30. data/lib/json-schema/attributes/limits/maximum.rb +15 -0
  31. data/lib/json-schema/attributes/limits/maximum_inclusive.rb +11 -0
  32. data/lib/json-schema/attributes/limits/min_items.rb +15 -0
  33. data/lib/json-schema/attributes/limits/min_length.rb +15 -0
  34. data/lib/json-schema/attributes/limits/min_properties.rb +15 -0
  35. data/lib/json-schema/attributes/limits/minimum.rb +15 -0
  36. data/lib/json-schema/attributes/limits/minimum_inclusive.rb +11 -0
  37. data/lib/json-schema/attributes/limits/numeric.rb +16 -0
  38. data/lib/json-schema/attributes/limits/properties.rb +15 -0
  39. data/lib/json-schema/attributes/maxdecimal.rb +18 -0
  40. data/lib/json-schema/attributes/multipleof.rb +11 -0
  41. data/lib/json-schema/attributes/not.rb +30 -0
  42. data/lib/json-schema/attributes/oneof.rb +56 -0
  43. data/lib/json-schema/attributes/pattern.rb +18 -0
  44. data/lib/json-schema/attributes/patternproperties.rb +22 -0
  45. data/lib/json-schema/attributes/properties.rb +66 -0
  46. data/lib/json-schema/attributes/properties_optional.rb +26 -0
  47. data/lib/json-schema/attributes/properties_v4.rb +13 -0
  48. data/lib/json-schema/attributes/ref.rb +61 -0
  49. data/lib/json-schema/attributes/required.rb +28 -0
  50. data/lib/json-schema/attributes/type.rb +73 -0
  51. data/lib/json-schema/attributes/type_v4.rb +29 -0
  52. data/lib/json-schema/attributes/uniqueitems.rb +20 -0
  53. data/lib/json-schema/errors/custom_format_error.rb +6 -0
  54. data/lib/json-schema/errors/json_load_error.rb +6 -0
  55. data/lib/json-schema/errors/json_parse_error.rb +6 -0
  56. data/lib/json-schema/errors/schema_error.rb +6 -0
  57. data/lib/json-schema/errors/schema_parse_error.rb +8 -0
  58. data/lib/json-schema/errors/uri_error.rb +6 -0
  59. data/lib/json-schema/errors/validation_error.rb +46 -0
  60. data/lib/json-schema/schema/reader.rb +140 -0
  61. data/lib/json-schema/schema/validator.rb +40 -0
  62. data/lib/json-schema/schema.rb +62 -0
  63. data/lib/json-schema/util/array_set.rb +20 -0
  64. data/lib/json-schema/util/uri.rb +110 -0
  65. data/lib/json-schema/util/uuid.rb +284 -0
  66. data/lib/json-schema/validator.rb +609 -0
  67. data/lib/json-schema/validators/draft1.rb +45 -0
  68. data/lib/json-schema/validators/draft2.rb +46 -0
  69. data/lib/json-schema/validators/draft3.rb +50 -0
  70. data/lib/json-schema/validators/draft4.rb +56 -0
  71. data/lib/json-schema/validators/draft6.rb +56 -0
  72. data/lib/json-schema/validators/hyper-draft1.rb +13 -0
  73. data/lib/json-schema/validators/hyper-draft2.rb +13 -0
  74. data/lib/json-schema/validators/hyper-draft3.rb +13 -0
  75. data/lib/json-schema/validators/hyper-draft4.rb +13 -0
  76. data/lib/json-schema/validators/hyper-draft6.rb +13 -0
  77. data/lib/json-schema.rb +18 -0
  78. data/resources/draft-01.json +155 -0
  79. data/resources/draft-02.json +166 -0
  80. data/resources/draft-03.json +174 -0
  81. data/resources/draft-04.json +150 -0
  82. data/resources/draft-06.json +150 -0
  83. metadata +197 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 229c79fe08ec97502b0d3d7fb9384655af26b050fdc0b545ae4a286684cf130b
4
+ data.tar.gz: 9e1777a533de9c1abab5bd537f28ef0ed7000da0368558847e314e0f258a18bf
5
+ SHA512:
6
+ metadata.gz: 1ce322cce67da1ef9094291fc34f537135ce26af2f0c3bd292a9a4775404b6a6d866d846e9a7e982c8589292b9ae4510af3d2ac6b6dd5e148f6a1f0a66b1b818
7
+ data.tar.gz: c53a0aed220852d9bbe67faf49a5cfd51310eb4b77729a4a5f64899fa66e2895945e46164d3cc64f3f7881c42d46827e0c0de82223b57585a5a5374577198cce
data/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010-2011, Lookingglass Cyber Solutions
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,496 @@
1
+ # Ruby JSON Schema Validator
2
+
3
+ [![License](https://img.shields.io/github/license/voxpupuli/json-schema.svg)](https://github.com/voxpupuli/json-schema/blob/master/LICENSE)
4
+ [![Test](https://github.com/voxpupuli/json-schema/actions/workflows/test.yml/badge.svg)](https://github.com/voxpupuli/json-schema/actions/workflows/test.yml)
5
+ [![Release](https://github.com/voxpupuli/json-schema/actions/workflows/release.yml/badge.svg)](https://github.com/voxpupuli/json-schema/actions/workflows/release.yml)
6
+ [![RubyGem Version](https://img.shields.io/gem/v/json-schema.svg)](https://rubygems.org/gems/json-schema)
7
+ [![RubyGem Downloads](https://img.shields.io/gem/dt/json-schema.svg)](https://rubygems.org/gems/json-schema)
8
+ [![Donated by Iain Beeston](https://img.shields.io/badge/donated%20by-Iain%20Beeston-fb7047.svg)](#transfer-notice)
9
+
10
+ This library is intended to provide Ruby with an interface for validating JSON
11
+ objects against a JSON schema conforming to [JSON Schema Draft
12
+ 4](http://tools.ietf.org/html/draft-zyp-json-schema-04). Legacy support for
13
+ [JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03),
14
+ [JSON Schema Draft 2](http://tools.ietf.org/html/draft-zyp-json-schema-02), and
15
+ [JSON Schema Draft 1](http://tools.ietf.org/html/draft-zyp-json-schema-01) is
16
+ also included.
17
+
18
+ Additional Resources
19
+ --------------------
20
+
21
+ - [Google Groups](https://groups.google.com/forum/#!forum/ruby-json-schema)
22
+ - #ruby-json-schema on chat.freenode.net
23
+
24
+ Version 2.0.0 Upgrade Notes
25
+ ---------------------------
26
+
27
+ Please be aware that the upgrade to version 2.0.0 will use Draft-04 **by
28
+ default**, so schemas that do not declare a validator using the `$schema`
29
+ keyword will use Draft-04 now instead of Draft-03. This is the reason for the
30
+ major version upgrade.
31
+
32
+ Installation
33
+ ------------
34
+
35
+ From rubygems.org:
36
+
37
+ ```sh
38
+ gem install json-schema
39
+ ```
40
+
41
+ From the git repo:
42
+
43
+ ```sh
44
+ $ gem build json-schema.gemspec
45
+ $ gem install json-schema-2.5.2.gem
46
+ ```
47
+
48
+ Validation
49
+ -----
50
+
51
+ Three base validation methods exist:
52
+
53
+ 1. `validate`: returns a boolean on whether a validation attempt passes
54
+ 2. `validate!`: throws a `JSON::Schema::ValidationError` with an appropriate message/trace on where the validation failed
55
+ 3. `fully_validate`: builds an array of validation errors return when validation is complete
56
+
57
+ All methods take two arguments, which can be either a JSON string, a file
58
+ containing JSON, or a Ruby object representing JSON data. The first argument to
59
+ these methods is always the schema, the second is always the data to validate.
60
+ An optional third options argument is also accepted; available options are used
61
+ in the examples below.
62
+
63
+ By default, the validator uses the [JSON Schema Draft
64
+ 4](http://tools.ietf.org/html/draft-zyp-json-schema-04) specification for
65
+ validation; however, the user is free to specify additional specifications or
66
+ extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is
67
+ included by either passing an optional `:version` parameter to the `validate`
68
+ method (set either as `:draft1` or `draft2`), or by declaring the `$schema`
69
+ attribute in the schema and referencing the appropriate specification URI. Note
70
+ that the `$schema` attribute takes precedence over the `:version` option during
71
+ parsing and validation.
72
+
73
+ For further information on json schema itself refer to <a
74
+ href="http://spacetelescope.github.io/understanding-json-schema/">Understanding
75
+ JSON Schema</a>.
76
+
77
+ Basic Usage
78
+ --------------
79
+
80
+ ```ruby
81
+ require "json-schema"
82
+
83
+ schema = {
84
+ "type" => "object",
85
+ "required" => ["a"],
86
+ "properties" => {
87
+ "a" => {"type" => "integer"}
88
+ }
89
+ }
90
+
91
+ #
92
+ # validate ruby objects against a ruby schema
93
+ #
94
+
95
+ # => true
96
+ JSON::Validator.validate(schema, { "a" => 5 })
97
+ # => false
98
+ JSON::Validator.validate(schema, {})
99
+
100
+ #
101
+ # validate a json string against a json schema file
102
+ #
103
+
104
+ require "json"
105
+ File.write("schema.json", JSON.dump(schema))
106
+
107
+ # => true
108
+ JSON::Validator.validate('schema.json', '{ "a": 5 }')
109
+
110
+ #
111
+ # raise an error when validation fails
112
+ #
113
+
114
+ # => "The property '#/a' of type String did not match the following type: integer"
115
+ begin
116
+ JSON::Validator.validate!(schema, { "a" => "taco" })
117
+ rescue JSON::Schema::ValidationError => e
118
+ e.message
119
+ end
120
+
121
+ #
122
+ # return an array of error messages when validation fails
123
+ #
124
+
125
+ # => ["The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f"]
126
+ JSON::Validator.fully_validate(schema, { "a" => "taco" })
127
+ ```
128
+
129
+ Advanced Options
130
+ -----------------
131
+
132
+ ```ruby
133
+ require "json-schema"
134
+
135
+ schema = {
136
+ "type"=>"object",
137
+ "required" => ["a"],
138
+ "properties" => {
139
+ "a" => {
140
+ "type" => "integer",
141
+ "default" => 42
142
+ },
143
+ "b" => {
144
+ "type" => "object",
145
+ "properties" => {
146
+ "x" => {
147
+ "type" => "integer"
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ #
155
+ # with the `:list` option, a list can be validated against a schema that represents the individual objects
156
+ #
157
+
158
+ # => true
159
+ JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}], :list => true)
160
+ # => false
161
+ JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}])
162
+
163
+ #
164
+ # with the `:errors_as_objects` option, `#fully_validate` returns errors as hashes instead of strings
165
+ #
166
+
167
+ # => [{:schema=>#<Addressable::URI:0x3ffa69cbeed8 URI:18a1ffbb-4681-5b00-bd15-2c76aee4b28f>, :fragment=>"#/a", :message=>"The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f", :failed_attribute=>"TypeV4"}]
168
+ JSON::Validator.fully_validate(schema, { "a" => "taco" }, :errors_as_objects => true)
169
+
170
+ #
171
+ # with the `:strict` option, all properties are considered to have `"required": true` and all objects `"additionalProperties": false`
172
+ #
173
+
174
+ # => true
175
+ JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 } }, :strict => true)
176
+ # => false
177
+ JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 }, "c" => 3 }, :strict => true)
178
+ # => false
179
+ JSON::Validator.validate(schema, { "a" => 1 }, :strict => true)
180
+
181
+ #
182
+ # with the `:fragment` option, only a fragment of the schema is used for validation
183
+ #
184
+
185
+ # => true
186
+ JSON::Validator.validate(schema, { "x" => 1 }, :fragment => "#/properties/b")
187
+ # => false
188
+ JSON::Validator.validate(schema, { "x" => 1 })
189
+
190
+ #
191
+ # with the `:validate_schema` option, the schema is validated (against the json schema spec) before the json is validated (against the specified schema)
192
+ #
193
+
194
+ # => true
195
+ JSON::Validator.validate(schema, { "a" => 1 }, :validate_schema => true)
196
+ # => false
197
+ JSON::Validator.validate({ "required" => true }, { "a" => 1 }, :validate_schema => true)
198
+
199
+ #
200
+ # with the `:insert_defaults` option, any undefined values in the json that have a default in the schema are replaced with the default before validation
201
+ #
202
+
203
+ # => true
204
+ JSON::Validator.validate(schema, {}, :insert_defaults => true)
205
+ # => false
206
+ JSON::Validator.validate(schema, {})
207
+
208
+ #
209
+ # with the `:version` option, schemas conforming to older drafts of the json schema spec can be used
210
+ #
211
+
212
+ v2_schema = {
213
+ "type" => "object",
214
+ "properties" => {
215
+ "a" => {
216
+ "type" => "integer"
217
+ }
218
+ }
219
+ }
220
+
221
+ # => false
222
+ JSON::Validator.validate(v2_schema, {}, :version => :draft2)
223
+ # => true
224
+ JSON::Validator.validate(v2_schema, {})
225
+
226
+ #
227
+ # with the `:parse_data` option set to false, the json must be a parsed ruby object (not a json text, a uri or a file path)
228
+ #
229
+
230
+ # => true
231
+ JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false)
232
+ # => false
233
+ JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false)
234
+
235
+ #
236
+ # with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path)
237
+ #
238
+
239
+ # => true
240
+ JSON::Validator.validate(schema, '{ "a": 1 }', :json => true)
241
+ # => "no implicit conversion of Hash into String"
242
+ begin
243
+ JSON::Validator.validate(schema, { "a" => 1 }, :json => true)
244
+ rescue TypeError => e
245
+ e.message
246
+ end
247
+
248
+ #
249
+ # with the `:uri` option, the json must be a uri or file path (not a hash or a json text)
250
+ #
251
+
252
+ File.write("data.json", '{ "a": 1 }')
253
+
254
+ # => true
255
+ JSON::Validator.validate(schema, "data.json", :uri => true)
256
+ # => "Can't convert Hash into String."
257
+ begin
258
+ JSON::Validator.validate(schema, { "a" => 1 }, :uri => true)
259
+ rescue TypeError => e
260
+ e.message
261
+ end
262
+
263
+ #
264
+ # with the `:clear_cache` option set to true, the internal cache of schemas is
265
+ # cleared after validation (otherwise schemas are cached for efficiency)
266
+ #
267
+
268
+ File.write("schema.json", v2_schema.to_json)
269
+
270
+ # => true
271
+ JSON::Validator.validate("schema.json", {})
272
+
273
+ File.write("schema.json", schema.to_json)
274
+
275
+ # => true
276
+ JSON::Validator.validate("schema.json", {}, :clear_cache => true)
277
+
278
+ # => false
279
+ JSON::Validator.validate("schema.json", {})
280
+ ```
281
+
282
+ Extending Schemas
283
+ -----------------
284
+
285
+ For this example, we are going to extend the [JSON Schema Draft
286
+ 3](http://tools.ietf.org/html/draft-zyp-json-schema-03) specification by adding
287
+ a 'bitwise-and' property for validation.
288
+
289
+ ```ruby
290
+ require "json-schema"
291
+
292
+ class BitwiseAndAttribute < JSON::Schema::Attribute
293
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
294
+ if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0
295
+ message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-or']}"
296
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
297
+ end
298
+ end
299
+ end
300
+
301
+ class ExtendedSchema < JSON::Schema::Draft3
302
+ def initialize
303
+ super
304
+ @attributes["bitwise-and"] = BitwiseAndAttribute
305
+ @uri = JSON::Util::URI.parse("http://test.com/test.json")
306
+ @names = ["http://test.com/test.json"]
307
+ end
308
+
309
+ JSON::Validator.register_validator(self.new)
310
+ end
311
+
312
+ schema = {
313
+ "$schema" => "http://test.com/test.json",
314
+ "properties" => {
315
+ "a" => {
316
+ "bitwise-and" => 1
317
+ },
318
+ "b" => {
319
+ "type" => "string"
320
+ }
321
+ }
322
+ }
323
+
324
+ data = {
325
+ "a" => 0
326
+ }
327
+
328
+ data = {"a" => 1, "b" => "taco"}
329
+ JSON::Validator.validate(schema,data) # => true
330
+ data = {"a" => 1, "b" => 5}
331
+ JSON::Validator.validate(schema,data) # => false
332
+ data = {"a" => 0, "b" => "taco"}
333
+ JSON::Validator.validate(schema,data) # => false
334
+ ```
335
+
336
+ Custom format validation
337
+ ------------------------
338
+
339
+ The JSON schema standard allows custom formats in schema definitions which
340
+ should be ignored by validators that do not support them. JSON::Schema allows
341
+ registering procs as custom format validators which receive the value to be
342
+ checked as parameter and must raise a `JSON::Schema::CustomFormatError` to
343
+ indicate a format violation. The error message will be prepended by the property
344
+ name, e.g. [The property '#a']()
345
+
346
+ ```ruby
347
+ require "json-schema"
348
+
349
+ format_proc = -> value {
350
+ raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42"
351
+ }
352
+
353
+ # register the proc for format 'the-answer' for draft4 schema
354
+ JSON::Validator.register_format_validator("the-answer", format_proc, ["draft4"])
355
+
356
+ # omitting the version parameter uses ["draft1", "draft2", "draft3", "draft4"] as default
357
+ JSON::Validator.register_format_validator("the-answer", format_proc)
358
+
359
+ # deregistering the custom validator
360
+ # (also ["draft1", "draft2", "draft3", "draft4"] as default version)
361
+ JSON::Validator.deregister_format_validator('the-answer', ["draft4"])
362
+
363
+ # shortcut to restore the default formats for validators (same default as before)
364
+ JSON::Validator.restore_default_formats(["draft4"])
365
+
366
+ # with the validator registered as above, the following results in
367
+ # ["The property '#a' must be 42"] as returned errors
368
+ schema = {
369
+ "$schema" => "http://json-schema.org/draft-04/schema#",
370
+ "properties" => {
371
+ "a" => {
372
+ "type" => "string",
373
+ "format" => "the-answer",
374
+ }
375
+ }
376
+ }
377
+ errors = JSON::Validator.fully_validate(schema, {"a" => "23"})
378
+ ```
379
+
380
+ Validating a JSON Schema
381
+ ------------------------
382
+
383
+ To validate that a JSON Schema conforms to the JSON Schema standard,
384
+ you need to validate your schema against the metaschema for the appropriate
385
+ JSON Schema Draft. All of the normal validation methods can be used
386
+ for this. First retrieve the appropriate metaschema from the internal
387
+ cache (using `JSON::Validator.validator_for_name()` or
388
+ `JSON::Validator.validator_for_uri()`) and then simply validate your
389
+ schema against it.
390
+
391
+
392
+ ```ruby
393
+ require "json-schema"
394
+
395
+ schema = {
396
+ "type" => "object",
397
+ "properties" => {
398
+ "a" => {"type" => "integer"}
399
+ }
400
+ }
401
+
402
+ metaschema = JSON::Validator.validator_for_name("draft4").metaschema
403
+ # => true
404
+ JSON::Validator.validate(metaschema, schema)
405
+ ```
406
+
407
+ Controlling Remote Schema Reading
408
+ ---------------------------------
409
+
410
+ In some cases, you may wish to prevent the JSON Schema library from making HTTP
411
+ calls or reading local files in order to resolve `$ref` schemas. If you fully
412
+ control all schemas which should be used by validation, this could be
413
+ accomplished by registering all referenced schemas with the validator in
414
+ advance:
415
+
416
+ ```ruby
417
+ schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema'))
418
+ JSON::Validator.add_schema(schema)
419
+ ```
420
+
421
+ If more extensive control is necessary, the `JSON::Schema::Reader` instance used
422
+ can be configured in a few ways:
423
+
424
+ ```ruby
425
+ # Change the default schema reader used
426
+ JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)
427
+
428
+ # For this validation call, use a reader which only accepts URIs from my-website.com
429
+ schema_reader = JSON::Schema::Reader.new(
430
+ :accept_uri => proc { |uri| uri.host == 'my-website.com' }
431
+ )
432
+ JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader)
433
+ ```
434
+
435
+ The `JSON::Schema::Reader` interface requires only an object which responds to
436
+ `read(string)` and returns a `JSON::Schema` instance. See the [API
437
+ documentation](http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader)
438
+ for more information.
439
+
440
+ JSON Backends
441
+ -------------
442
+
443
+ The JSON Schema library currently supports the `json` and `yajl-ruby` backend
444
+ JSON parsers. If either of these libraries are installed, they will be
445
+ automatically loaded and used to parse any JSON strings supplied by the user.
446
+
447
+ If more than one of the supported JSON backends are installed, the `yajl-ruby`
448
+ parser is used by default. This can be changed by issuing the following before
449
+ validation:
450
+
451
+ ```ruby
452
+ JSON::Validator.json_backend = :json
453
+ ```
454
+
455
+ Optionally, the JSON Schema library supports using the MultiJSON library for
456
+ selecting JSON backends. If the MultiJSON library is installed, it will be
457
+ autoloaded.
458
+
459
+ Notes
460
+ -----
461
+
462
+ The 'format' attribute is only validated for the following values:
463
+
464
+ - date-time
465
+ - date
466
+ - time
467
+ - ip-address (IPv4 address in draft1, draft2 and draft3)
468
+ - ipv4 (IPv4 address in draft4)
469
+ - ipv6
470
+ - uri
471
+
472
+ All other 'format' attribute values are simply checked to ensure the instance
473
+ value is of the correct datatype (e.g., an instance value is validated to be an
474
+ integer or a float in the case of 'utc-millisec').
475
+
476
+ Additionally, JSON::Validator does not handle any json hyperschema attributes.
477
+
478
+ # Transfer Notice
479
+
480
+ This plugin was originally authored by [Iain Beeston](https://github.com/iainbeeston).
481
+ The maintainer preferred that [Vox Pupuli](https://voxpupuli.org/) take ownership of the module for future improvement and maintenance.
482
+ Existing pull requests and issues were transferred, please fork and continue to contribute [here](https://github.com/voxpupuli/json-schema).
483
+
484
+ # License
485
+
486
+ This gem is licensed unter the [MIT license](LICENSE.md).
487
+
488
+ ## Release information
489
+
490
+ To make a new release, please do:
491
+ * update the version in VERSION.yml
492
+ * Install gems with `bundle install --with release --path .vendor`
493
+ * generate the changelog with `bundle exec rake changelog`
494
+ * Check if the new version matches the closed issues/PRs in the changelog
495
+ * Create a PR with it
496
+ * After it got merged, push a tag. GitHub actions will do the actual release to rubygems and GitHub Packages
@@ -0,0 +1,57 @@
1
+ require 'json-schema/errors/validation_error'
2
+
3
+ module JSON
4
+ class Schema
5
+ class Attribute
6
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
+ end
8
+
9
+ def self.build_fragment(fragments)
10
+ "#/#{fragments.join('/')}"
11
+ end
12
+
13
+ def self.validation_error(processor, message, fragments, current_schema, failed_attribute, record_errors)
14
+ error = ValidationError.new(message, fragments, failed_attribute, current_schema)
15
+ if record_errors
16
+ processor.validation_error(error)
17
+ else
18
+ raise error
19
+ end
20
+ end
21
+
22
+ def self.validation_errors(validator)
23
+ validator.validation_errors
24
+ end
25
+
26
+ TYPE_CLASS_MAPPINGS = {
27
+ "string" => String,
28
+ "number" => Numeric,
29
+ "integer" => Integer,
30
+ "boolean" => [TrueClass, FalseClass],
31
+ "object" => Hash,
32
+ "array" => Array,
33
+ "null" => NilClass,
34
+ "any" => Object
35
+ }
36
+
37
+ def self.data_valid_for_type?(data, type)
38
+ valid_classes = TYPE_CLASS_MAPPINGS.fetch(type) { return true }
39
+ Array(valid_classes).any? { |c| data.is_a?(c) }
40
+ end
41
+
42
+ # Lookup Schema type of given class instance
43
+ def self.type_of_data(data)
44
+ type, _ = TYPE_CLASS_MAPPINGS.map { |k,v| [k,v] }.sort_by { |(_, v)|
45
+ -Array(v).map { |klass| klass.ancestors.size }.max
46
+ }.find { |(_, v)|
47
+ Array(v).any? { |klass| data.kind_of?(klass) }
48
+ }
49
+ type
50
+ end
51
+
52
+ def self.validate_on_false?
53
+ true
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ require 'json-schema/attribute'
2
+
3
+ module JSON
4
+ class Schema
5
+ class AdditionalItemsAttribute < Attribute
6
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
7
+ return unless data.is_a?(Array)
8
+
9
+ schema = current_schema.schema
10
+ return unless schema['items'].is_a?(Array)
11
+
12
+ case schema['additionalItems']
13
+ when false
14
+ if schema['items'].length < data.length
15
+ message = "The property '#{build_fragment(fragments)}' contains additional array elements outside of the schema when none are allowed"
16
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
17
+ end
18
+ when Hash
19
+ additional_items_schema = JSON::Schema.new(schema['additionalItems'], current_schema.uri, validator)
20
+ data.each_with_index do |item, i|
21
+ next if i < schema['items'].length
22
+ additional_items_schema.validate(item, fragments + [i.to_s], processor, options)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,58 @@
1
+ require 'json-schema/attribute'
2
+ require 'json-schema/attributes/extends'
3
+
4
+ module JSON
5
+ class Schema
6
+ class AdditionalPropertiesAttribute < Attribute
7
+ def self.validate(current_schema, data, fragments, processor, validator, options = {})
8
+ schema = current_schema.schema
9
+ return unless data.is_a?(Hash) && (schema['type'].nil? || schema['type'] == 'object')
10
+
11
+ extra_properties = remove_valid_properties(data.keys, current_schema, validator)
12
+
13
+ addprop = schema['additionalProperties']
14
+ if addprop.is_a?(Hash)
15
+ matching_properties = extra_properties # & addprop.keys
16
+ matching_properties.each do |key|
17
+ additional_property_schema = JSON::Schema.new(addprop, current_schema.uri, validator)
18
+ additional_property_schema.validate(data[key], fragments + [key], processor, options)
19
+ end
20
+ extra_properties -= matching_properties
21
+ end
22
+
23
+ if extra_properties.any? && (addprop == false || (addprop.is_a?(Hash) && !addprop.empty?))
24
+ message = "The property '#{build_fragment(fragments)}' contains additional properties #{extra_properties.inspect} outside of the schema when none are allowed"
25
+ validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
26
+ end
27
+ end
28
+
29
+ def self.remove_valid_properties(extra_properties, current_schema, validator)
30
+ schema = current_schema.schema
31
+
32
+ if schema['properties']
33
+ extra_properties = extra_properties - schema['properties'].keys
34
+ end
35
+
36
+ if schema['patternProperties']
37
+ schema['patternProperties'].each_key do |key|
38
+ regexp = Regexp.new(key)
39
+ extra_properties.reject! { |prop| regexp.match(prop) }
40
+ end
41
+ end
42
+
43
+ if extended_schemas = schema['extends']
44
+ extended_schemas = [extended_schemas] unless extended_schemas.is_a?(Array)
45
+ extended_schemas.each do |schema_value|
46
+ _, extended_schema = JSON::Schema::ExtendsAttribute.get_extended_uri_and_schema(schema_value, current_schema, validator)
47
+ if extended_schema
48
+ extra_properties = remove_valid_properties(extra_properties, extended_schema, validator)
49
+ end
50
+ end
51
+ end
52
+
53
+ extra_properties
54
+ end
55
+
56
+ end
57
+ end
58
+ end