jsonschema_rs 0.58.4-aarch64-linux → 0.58.6-aarch64-linux
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/CHANGELOG.md +18 -1
- data/README.md +97 -65
- data/lib/jsonschema/3.3/jsonschema_rb.so +0 -0
- data/lib/jsonschema/3.4/jsonschema_rb.so +0 -0
- data/lib/jsonschema/4.0/jsonschema_rb.so +0 -0
- data/lib/jsonschema/version.rb +1 -1
- data/sig/jsonschema.rbs +18 -9
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 101db82b32ba8aa6dbfd06740f4043ab606607ffdd22f7214be3b89ecfd0f8dd
|
|
4
|
+
data.tar.gz: c9fd3b007afd9d0d7451f4dd4a5c2ea32c63305eac03d1f121f17530ef4d0162
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 328637f780630df882eb5e0ebbf91c3b8611fd833f3e607b8560b995b602be96c5f37222720328ebf99d02b52f555496438f54e878744f6c7b130a0f2e24236a
|
|
7
|
+
data.tar.gz: e26a19411713753ddbd69b4c743e0a13c97eccecd103fd8d042157c2d2e9aec7eaac767a0d3f19d1fb7989c88d52de1c20a3ca3005657b1f00f9db20681978e0
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.58.6] - 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- ECMA regex character class literals being interpreted as Rust set operators.
|
|
10
|
+
- Installing the source gem.
|
|
11
|
+
- `\s` in `pattern` missing most Unicode space separators and U+2028.
|
|
12
|
+
|
|
13
|
+
## [0.58.5] - 2026-10-02
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `canonicalize` keeping a reference to a cycle of bare references under `not` or `oneOf` instead of treating it as accepting every value.
|
|
18
|
+
- Validator construction holding the GVL while it retrieves external resources over HTTP or from files.
|
|
19
|
+
|
|
5
20
|
## [0.58.4] - 2026-10-01
|
|
6
21
|
|
|
7
22
|
### Fixed
|
|
@@ -637,7 +652,9 @@
|
|
|
637
652
|
|
|
638
653
|
- Initial public release
|
|
639
654
|
|
|
640
|
-
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.
|
|
655
|
+
[Unreleased]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.6...HEAD
|
|
656
|
+
[0.58.6]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.5...ruby-v0.58.6
|
|
657
|
+
[0.58.5]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.4...ruby-v0.58.5
|
|
641
658
|
[0.58.4]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.3...ruby-v0.58.4
|
|
642
659
|
[0.58.3]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.2...ruby-v0.58.3
|
|
643
660
|
[0.58.2]: https://github.com/Stranger6667/jsonschema/compare/ruby-v0.58.1...ruby-v0.58.2
|
data/README.md
CHANGED
|
@@ -45,29 +45,29 @@ end
|
|
|
45
45
|
|
|
46
46
|
## Highlights
|
|
47
47
|
|
|
48
|
-
- 📚
|
|
49
|
-
- 🌐 Remote reference fetching (network/file)
|
|
48
|
+
- 📚 Drafts 4, 6, 7, 2019-09 and 2020-12
|
|
50
49
|
- 🔧 Custom keywords and format validators
|
|
51
|
-
-
|
|
50
|
+
- ⚡ Compile-time validators for your own native extensions, via the Rust crate
|
|
51
|
+
- 🌐 `$ref` resolution over HTTP and from files
|
|
52
52
|
- 📦 Schema bundling into Compound Schema Documents, and `$ref` dereferencing
|
|
53
|
+
- 🎨 Structured Output v1 reports (flag/list/hierarchical)
|
|
54
|
+
- ✨ Meta-schema validation for schema documents, including custom metaschemas
|
|
53
55
|
- 🧮 Experimental schema canonicalization
|
|
54
56
|
- ♦️ Supports Ruby 3.2, 3.4 and 4.0
|
|
55
57
|
|
|
56
58
|
### Supported drafts
|
|
57
59
|
|
|
58
|
-
The following drafts are supported:
|
|
59
|
-
|
|
60
60
|
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
61
61
|
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
62
62
|
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
63
63
|
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
64
64
|
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Per-draft compliance results are on the [Bowtie Report](https://bowtie.report/#/implementations/rust-jsonschema).
|
|
67
67
|
|
|
68
68
|
## Playground
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Try schemas in the browser with the WebAssembly [playground](https://jsonschema.dygalo.dev/).
|
|
71
71
|
|
|
72
72
|
## Installation
|
|
73
73
|
|
|
@@ -77,13 +77,13 @@ Add to your Gemfile:
|
|
|
77
77
|
gem 'jsonschema_rs'
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
Pre-built native gems
|
|
80
|
+
Pre-built native gems:
|
|
81
81
|
|
|
82
82
|
- **Linux**: `x86_64`, `aarch64` (glibc and musl)
|
|
83
83
|
- **macOS**: `x86_64`, `arm64`
|
|
84
84
|
- **Windows**: `x64` (mingw-ucrt)
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
On other platforms, `gem install` compiles from source and needs:
|
|
87
87
|
- Ruby 3.2+
|
|
88
88
|
- Rust toolchain ([rustup](https://rustup.rs/))
|
|
89
89
|
|
|
@@ -91,8 +91,8 @@ If no pre-built gem is available for your platform, it will be compiled from sou
|
|
|
91
91
|
|
|
92
92
|
### Reusable validators
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
`validator_for`
|
|
94
|
+
Build a validator once to check many instances against one schema.
|
|
95
|
+
`validator_for` detects the draft from `$schema` and falls back to Draft 2020-12:
|
|
96
96
|
|
|
97
97
|
```ruby
|
|
98
98
|
validator = JSONSchema.validator_for({
|
|
@@ -108,7 +108,7 @@ validator.valid?({ "name" => "Alice", "age" => 30 }) # => true
|
|
|
108
108
|
validator.valid?({ "age" => 30 }) # => false
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
To pick the draft yourself, use a draft-specific class:
|
|
112
112
|
|
|
113
113
|
```ruby
|
|
114
114
|
validator = JSONSchema::Draft7Validator.new(schema)
|
|
@@ -119,6 +119,8 @@ validator = JSONSchema::Draft7Validator.new(schema)
|
|
|
119
119
|
|
|
120
120
|
### Custom format validators
|
|
121
121
|
|
|
122
|
+
Pass a callable that takes a `String` and returns a boolean via `formats`. Drafts 2019-09 and 2020-12 treat `format` as an annotation, so set `validate_formats: true` to get it checked:
|
|
123
|
+
|
|
122
124
|
```ruby
|
|
123
125
|
phone_format = ->(value) { value.match?(/^\+?[1-9]\d{1,14}$/) }
|
|
124
126
|
|
|
@@ -150,10 +152,10 @@ validator = JSONSchema.validator_for(
|
|
|
150
152
|
```
|
|
151
153
|
|
|
152
154
|
Each custom keyword class must implement:
|
|
153
|
-
- `initialize(parent_schema, value, schema_path)
|
|
154
|
-
- `validate(instance)
|
|
155
|
+
- `initialize(parent_schema, value, schema_path)`: called once when the validator is built
|
|
156
|
+
- `validate(instance)`: raise to reject the value, return to accept it
|
|
155
157
|
|
|
156
|
-
|
|
158
|
+
To report several problems from one keyword, also implement `iter_errors(instance)` returning an array of exceptions. `each_error` yields each of them. Without it, `each_error` yields the single error from `validate`:
|
|
157
159
|
|
|
158
160
|
```ruby
|
|
159
161
|
class AllPositive
|
|
@@ -172,7 +174,7 @@ class AllPositive
|
|
|
172
174
|
end
|
|
173
175
|
```
|
|
174
176
|
|
|
175
|
-
|
|
177
|
+
The resulting `ValidationError` keeps the raised exception as `cause`, for both `validate` and `iter_errors`:
|
|
176
178
|
|
|
177
179
|
```ruby
|
|
178
180
|
begin
|
|
@@ -185,7 +187,7 @@ end
|
|
|
185
187
|
|
|
186
188
|
### Structured evaluation output
|
|
187
189
|
|
|
188
|
-
|
|
190
|
+
`evaluate` returns the [JSON Schema Output v1](https://json-schema.org/draft/2020-12/json-schema-core#name-output-formatting) formats instead of a boolean:
|
|
189
191
|
|
|
190
192
|
```ruby
|
|
191
193
|
schema = {
|
|
@@ -203,14 +205,14 @@ evaluation = validator.evaluate({ "age" => "not_an_integer" })
|
|
|
203
205
|
evaluation.valid? # => false
|
|
204
206
|
```
|
|
205
207
|
|
|
206
|
-
**Flag output
|
|
208
|
+
**Flag output**: valid or invalid, nothing else:
|
|
207
209
|
|
|
208
210
|
```ruby
|
|
209
211
|
evaluation.flag
|
|
210
212
|
# => {valid: false}
|
|
211
213
|
```
|
|
212
214
|
|
|
213
|
-
**List output
|
|
215
|
+
**List output**: every evaluation node in a flat list:
|
|
214
216
|
|
|
215
217
|
```ruby
|
|
216
218
|
evaluation.list
|
|
@@ -231,7 +233,7 @@ evaluation.list
|
|
|
231
233
|
# ]}
|
|
232
234
|
```
|
|
233
235
|
|
|
234
|
-
**Hierarchical output
|
|
236
|
+
**Hierarchical output**: the same nodes nested by schema structure:
|
|
235
237
|
|
|
236
238
|
```ruby
|
|
237
239
|
evaluation.hierarchical
|
|
@@ -255,7 +257,7 @@ evaluation.hierarchical
|
|
|
255
257
|
# ]}
|
|
256
258
|
```
|
|
257
259
|
|
|
258
|
-
**Collected errors
|
|
260
|
+
**Collected errors**: every error across all nodes:
|
|
259
261
|
|
|
260
262
|
```ruby
|
|
261
263
|
evaluation.errors
|
|
@@ -266,8 +268,8 @@ evaluation.errors
|
|
|
266
268
|
# error: "\"not_an_integer\" is not of type \"integer\""}]
|
|
267
269
|
```
|
|
268
270
|
|
|
269
|
-
**Collected annotations
|
|
270
|
-
|
|
271
|
+
**Collected annotations**: annotations from the nodes that passed.
|
|
272
|
+
A failed node reports its annotations as `droppedAnnotations` in the list and hierarchical output instead.
|
|
271
273
|
|
|
272
274
|
```ruby
|
|
273
275
|
valid_eval = validator.evaluate({ "name" => "Alice", "age" => 30 })
|
|
@@ -278,7 +280,7 @@ valid_eval.annotations
|
|
|
278
280
|
|
|
279
281
|
### Canonical JSON serialization
|
|
280
282
|
|
|
281
|
-
|
|
283
|
+
`Canonical::JSON.to_string` serializes equal JSON values to the same string, regardless of key order:
|
|
282
284
|
|
|
283
285
|
```ruby
|
|
284
286
|
schema_a = { "type" => "object", "properties" => { "b" => { "type" => "integer" }, "a" => { "type" => "string" } } }
|
|
@@ -290,13 +292,13 @@ dump_b = JSONSchema::Canonical::JSON.to_string(schema_b)
|
|
|
290
292
|
dump_a == dump_b # => true
|
|
291
293
|
```
|
|
292
294
|
|
|
293
|
-
|
|
295
|
+
Use it to deduplicate schemas that differ only in key order.
|
|
294
296
|
|
|
295
297
|
## Schema Canonicalization
|
|
296
298
|
|
|
297
299
|
> **Experimental**: the canonicalization API may change in minor releases.
|
|
298
300
|
|
|
299
|
-
`JSONSchema.canonicalize` reduces a schema to a normal form
|
|
301
|
+
`JSONSchema.canonicalize` reduces a schema to a normal form that accepts the same values. Schemas that accept the same values reduce to equal `CanonicalSchema` objects, and a schema proven to accept nothing reduces to `false`:
|
|
300
302
|
|
|
301
303
|
```ruby
|
|
302
304
|
canonical = JSONSchema.canonicalize(
|
|
@@ -315,7 +317,9 @@ JSONSchema.canonicalize({ "type" => "integer", "minimum" => 10, "maximum" => 5 }
|
|
|
315
317
|
# => :no, which is JSONSchema::Canonical::Satisfiability::NO
|
|
316
318
|
```
|
|
317
319
|
|
|
318
|
-
A canonical
|
|
320
|
+
A schema the canonical form cannot model exactly comes back unchanged, with `kind == :raw`. Its `view.reason` names what stopped the run, and `view.pointer` the subschema at fault when a single one is.
|
|
321
|
+
|
|
322
|
+
Canonical schemas combine like sets of values. Every emitted schema carries `$schema`; the comments below leave it out:
|
|
319
323
|
|
|
320
324
|
```ruby
|
|
321
325
|
positive = JSONSchema.canonicalize({ "type" => "integer", "minimum" => 0 })
|
|
@@ -333,19 +337,19 @@ positive.union(bounded).to_json_schema
|
|
|
333
337
|
positive.subtract(bounded).to_json_schema
|
|
334
338
|
# => {"type"=>"integer", "minimum"=>101}
|
|
335
339
|
|
|
336
|
-
# Every value `positive` rejects,
|
|
340
|
+
# Every value `positive` rejects: other types, negative integers and non-integer numbers
|
|
337
341
|
positive.negate.to_json_schema
|
|
338
342
|
# => {"anyOf"=>[{"type"=>["null", "boolean", "string", "array", "object"]},
|
|
339
343
|
# {"type"=>"integer", "maximum"=>-1},
|
|
340
344
|
# {"type"=>"number", "not"=>{"multipleOf"=>1}}]}
|
|
341
345
|
|
|
342
|
-
positive.covers(bounded) # => :no
|
|
346
|
+
positive.covers(bounded) # => :no: `bounded` takes negative integers, `positive` does not
|
|
343
347
|
positive.satisfiability # => :yes
|
|
344
348
|
```
|
|
345
349
|
|
|
346
350
|
### Comparing two versions of a schema
|
|
347
351
|
|
|
348
|
-
|
|
352
|
+
`subtract` tells you what an edit did to a schema. `old.subtract(new)` accepts exactly the values `old` accepts and `new` rejects, so it accepts nothing when the edit lost nothing.
|
|
349
353
|
|
|
350
354
|
```ruby
|
|
351
355
|
old = JSONSchema.canonicalize({ "type" => "string" })
|
|
@@ -361,19 +365,23 @@ new.subtract(old).satisfiability
|
|
|
361
365
|
# => :no
|
|
362
366
|
```
|
|
363
367
|
|
|
364
|
-
|
|
368
|
+
The direction to check depends on who sends the value:
|
|
365
369
|
|
|
366
|
-
|
|
370
|
+
- For a request schema, check `old.subtract(new)`. It accepts the payloads existing callers send that the new schema rejects.
|
|
371
|
+
- For a response schema, check `new.subtract(old)`. It accepts the values the new schema lets a server return that callers never agreed to read.
|
|
367
372
|
|
|
368
|
-
`:
|
|
373
|
+
`:no` on the difference proves the edit safe in that direction. `:unknown` means the canonicalizer could not decide, and proves nothing either way. Read it as the answer that keeps you safe:
|
|
374
|
+
|
|
375
|
+
- `satisfiability`: only `:no` proves a schema accepts nothing. Treat `:unknown` like `:yes`.
|
|
376
|
+
- `a.covers(b)`: only `:yes` proves `a` accepts every value `b` accepts. Treat `:unknown` like `:no`.
|
|
369
377
|
|
|
370
378
|
`JSONSchema::Canonical::Containment`, `Satisfiability`, `Distinctness` and `Kind` hold these symbols as constants, each with an `ALL` list.
|
|
371
379
|
|
|
372
|
-
|
|
380
|
+
The set operations raise `IncompatibleOperands` when the operands differ in draft, `format` assertion or regular-expression engine, or resolve `#` or one external resource to different schemas. They raise `UnsupportedOperand` when an operand is `:raw`, and `UnsupportedResult` when the canonical form cannot express the result exactly. All three live under `JSONSchema::Canonical`.
|
|
373
381
|
|
|
374
382
|
### Finding the dead subschemas of a document
|
|
375
383
|
|
|
376
|
-
`JSONSchema::Canonical.find_unsatisfiable` walks a whole document and
|
|
384
|
+
`JSONSchema::Canonical.find_unsatisfiable` walks a whole document and reports each subschema that accepts no value, with the keywords at fault and their pointers:
|
|
377
385
|
|
|
378
386
|
```ruby
|
|
379
387
|
reasons = JSONSchema::Canonical.find_unsatisfiable(
|
|
@@ -396,11 +404,11 @@ reasons.key?("/properties/name")
|
|
|
396
404
|
# => false
|
|
397
405
|
```
|
|
398
406
|
|
|
399
|
-
A reason is a `LiteralReason` (written as `false`), an `EmptyReason` (one part admits nothing by itself) or a `ConflictReason` (each part admits values, together they admit none). A pointer
|
|
407
|
+
A reason is a `LiteralReason` (written as `false`), an `EmptyReason` (one part admits nothing by itself) or a `ConflictReason` (each part admits values, together they admit none). A missing pointer does not prove that subschema satisfiable. For a document the canonical form cannot model, `find_unsatisfiable` reports nothing, the same way `satisfiability` answers `:unknown`.
|
|
400
408
|
|
|
401
409
|
## Schema Bundling and Dereferencing
|
|
402
410
|
|
|
403
|
-
Produce a Compound Schema Document ([Appendix B](https://json-schema.org/draft/2020-12/json-schema-core#appendix-B)) by embedding all external `$ref` targets into a draft-appropriate container. The
|
|
411
|
+
Produce a Compound Schema Document ([Appendix B](https://json-schema.org/draft/2020-12/json-schema-core#appendix-B)) by embedding all external `$ref` targets into a draft-appropriate container. The bundle accepts the same values as the original.
|
|
404
412
|
|
|
405
413
|
```ruby
|
|
406
414
|
address_schema = {
|
|
@@ -430,7 +438,7 @@ dereferenced = JSONSchema.dereference(schema, registry: registry)
|
|
|
430
438
|
|
|
431
439
|
## Meta-Schema Validation
|
|
432
440
|
|
|
433
|
-
|
|
441
|
+
`JSONSchema::Meta` checks a schema against the meta-schema of its draft:
|
|
434
442
|
|
|
435
443
|
```ruby
|
|
436
444
|
JSONSchema::Meta.valid?({ "type" => "string" }) # => true
|
|
@@ -443,9 +451,24 @@ rescue JSONSchema::ValidationError => e
|
|
|
443
451
|
end
|
|
444
452
|
```
|
|
445
453
|
|
|
454
|
+
For a custom metaschema, register it and point `$schema` at its URI:
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
metaschema = {
|
|
458
|
+
"$schema" => "https://json-schema.org/draft/2020-12/schema",
|
|
459
|
+
"$id" => "https://example.com/meta",
|
|
460
|
+
"type" => "object",
|
|
461
|
+
"required" => ["title"]
|
|
462
|
+
}
|
|
463
|
+
meta_registry = JSONSchema::Registry.new([["https://example.com/meta", metaschema]])
|
|
464
|
+
|
|
465
|
+
JSONSchema::Meta.valid?({ "$schema" => "https://example.com/meta", "title" => "Person" }, registry: meta_registry) # => true
|
|
466
|
+
JSONSchema::Meta.valid?({ "$schema" => "https://example.com/meta" }, registry: meta_registry) # => false
|
|
467
|
+
```
|
|
468
|
+
|
|
446
469
|
## External References
|
|
447
470
|
|
|
448
|
-
By default, `
|
|
471
|
+
By default, `jsonschema_rs` fetches external `$ref` targets over HTTP and from the local file system. Pass a `retriever:` to load them yourself:
|
|
449
472
|
|
|
450
473
|
```ruby
|
|
451
474
|
schemas = {
|
|
@@ -468,9 +491,21 @@ validator.valid?({ "name" => "Alice", "age" => 30 }) # => true
|
|
|
468
491
|
validator.valid?({ "name" => "Bob" }) # => false (missing "age")
|
|
469
492
|
```
|
|
470
493
|
|
|
494
|
+
For schemas from untrusted sources, pass `offline: true`. The validator then refuses to fetch any `$ref` target, so a schema cannot reach your network or file system. Schemas held in a `Registry` still resolve:
|
|
495
|
+
|
|
496
|
+
```ruby
|
|
497
|
+
begin
|
|
498
|
+
JSONSchema.validator_for({ "$ref" => "https://example.com/other.json" }, offline: true)
|
|
499
|
+
rescue JSONSchema::ReferencingError => e
|
|
500
|
+
e.message # => "Resource 'https://example.com/other.json' is not present in a registry ..."
|
|
501
|
+
end
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
`bundle` and `dereference` take `offline:` too.
|
|
505
|
+
|
|
471
506
|
## Schema Registry
|
|
472
507
|
|
|
473
|
-
|
|
508
|
+
A `Registry` holds schemas by URI, so a validator resolves `$ref`s to them without fetching anything:
|
|
474
509
|
|
|
475
510
|
```ruby
|
|
476
511
|
registry = JSONSchema::Registry.new([
|
|
@@ -501,7 +536,7 @@ validator.valid?({
|
|
|
501
536
|
}) # => true
|
|
502
537
|
```
|
|
503
538
|
|
|
504
|
-
|
|
539
|
+
`Registry` also takes a default `draft:` and a `retriever:` for URIs it does not hold:
|
|
505
540
|
|
|
506
541
|
```ruby
|
|
507
542
|
registry = JSONSchema::Registry.new(
|
|
@@ -513,7 +548,7 @@ registry = JSONSchema::Registry.new(
|
|
|
513
548
|
|
|
514
549
|
## Regular Expression Configuration
|
|
515
550
|
|
|
516
|
-
|
|
551
|
+
`pattern_options:` picks the regex engine for `pattern` and `patternProperties` and sets its limits:
|
|
517
552
|
|
|
518
553
|
```ruby
|
|
519
554
|
# Default fancy-regex engine with backtracking limits
|
|
@@ -540,24 +575,22 @@ validator = JSONSchema.validator_for(
|
|
|
540
575
|
)
|
|
541
576
|
```
|
|
542
577
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
- `FancyRegexOptions`: Default engine with lookaround and backreferences support
|
|
578
|
+
- `FancyRegexOptions`: default engine, supports lookaround and backreferences
|
|
546
579
|
|
|
547
580
|
- `backtrack_limit`: Maximum backtracking steps
|
|
548
581
|
- `size_limit`: Maximum compiled regex size in bytes
|
|
549
582
|
- `dfa_size_limit`: Maximum DFA cache size in bytes
|
|
550
583
|
|
|
551
|
-
- `RegexOptions`:
|
|
584
|
+
- `RegexOptions`: matches in linear time, no lookaround or backreferences
|
|
552
585
|
|
|
553
586
|
- `size_limit`: Maximum compiled regex size in bytes
|
|
554
587
|
- `dfa_size_limit`: Maximum DFA cache size in bytes
|
|
555
588
|
|
|
556
|
-
|
|
589
|
+
If you validate against schemas from untrusted sources, use `RegexOptions`: a crafted pattern cannot make it backtrack.
|
|
557
590
|
|
|
558
591
|
## Email Format Configuration
|
|
559
592
|
|
|
560
|
-
|
|
593
|
+
`email_options:` makes `{"format": "email"}` stricter or looser than the spec default:
|
|
561
594
|
|
|
562
595
|
```ruby
|
|
563
596
|
# Require a top-level domain (reject "user@localhost")
|
|
@@ -587,16 +620,14 @@ validator = JSONSchema.validator_for(
|
|
|
587
620
|
)
|
|
588
621
|
```
|
|
589
622
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
- `require_tld`: Require a top-level domain (e.g., reject "user@localhost")
|
|
623
|
+
- `require_tld`: Require a top-level domain (e.g., reject "user@localhost") (default: false)
|
|
593
624
|
- `allow_domain_literal`: Allow IP address literals like "user@[127.0.0.1]" (default: true)
|
|
594
625
|
- `allow_display_text`: Allow display names like "Name <user@example.com>" (default: true)
|
|
595
626
|
- `minimum_sub_domains`: Minimum number of domain segments required
|
|
596
627
|
|
|
597
628
|
## Error Handling
|
|
598
629
|
|
|
599
|
-
`
|
|
630
|
+
A `ValidationError` carries the message, both locations and a `kind` with keyword-specific details:
|
|
600
631
|
|
|
601
632
|
```ruby
|
|
602
633
|
schema = { "type" => "string", "maxLength" => 5 }
|
|
@@ -619,7 +650,7 @@ end
|
|
|
619
650
|
|
|
620
651
|
### Error Kind Properties
|
|
621
652
|
|
|
622
|
-
|
|
653
|
+
`kind` has generic accessors:
|
|
623
654
|
|
|
624
655
|
```ruby
|
|
625
656
|
JSONSchema.each_error({ "minimum" => 5 }, 3).each do |error|
|
|
@@ -632,7 +663,7 @@ end
|
|
|
632
663
|
|
|
633
664
|
### Error Message Masking
|
|
634
665
|
|
|
635
|
-
|
|
666
|
+
Pass `mask:` to replace instance values in error messages with a placeholder:
|
|
636
667
|
|
|
637
668
|
```ruby
|
|
638
669
|
schema = {
|
|
@@ -657,19 +688,19 @@ end
|
|
|
657
688
|
|
|
658
689
|
### Exception Classes
|
|
659
690
|
|
|
660
|
-
- **`JSONSchema::ValidationError
|
|
691
|
+
- **`JSONSchema::ValidationError`**: raised on validation failure
|
|
661
692
|
- `message`, `verbose_message`, `instance_path`, `schema_path`, `evaluation_path`, `kind`, `instance`
|
|
662
693
|
- JSON Pointer helpers: `instance_path_pointer`, `schema_path_pointer`, `evaluation_path_pointer`
|
|
663
|
-
- **`JSONSchema::ReferencingError
|
|
694
|
+
- **`JSONSchema::ReferencingError`**: raised when a `$ref` cannot be resolved
|
|
664
695
|
|
|
665
696
|
## Options Reference
|
|
666
697
|
|
|
667
|
-
|
|
698
|
+
The one-off methods `valid?`, `validate!` and `each_error` accept these keyword arguments:
|
|
668
699
|
|
|
669
700
|
```ruby
|
|
670
701
|
JSONSchema.valid?(schema, instance,
|
|
671
702
|
draft: :draft7, # Specific draft version (symbol)
|
|
672
|
-
validate_formats: true, #
|
|
703
|
+
validate_formats: true, # Check `format` (default: on up to Draft 7, off for 2019-09 and 2020-12)
|
|
673
704
|
ignore_unknown_formats: true, # Don't error on unknown formats (default: true)
|
|
674
705
|
base_uri: "https://example.com", # Base URI for reference resolution
|
|
675
706
|
mask: "[REDACTED]", # Mask sensitive data in error messages
|
|
@@ -680,25 +711,26 @@ JSONSchema.valid?(schema, instance,
|
|
|
680
711
|
vocabularies: ["https://..."], # Vocabularies implemented by custom keywords
|
|
681
712
|
pattern_options: opts, # RegexOptions or FancyRegexOptions
|
|
682
713
|
email_options: opts, # EmailOptions
|
|
683
|
-
http_options: opts
|
|
714
|
+
http_options: opts, # HttpOptions
|
|
715
|
+
offline: false # true refuses to fetch $refs; conflicts with retriever:
|
|
684
716
|
)
|
|
685
717
|
```
|
|
686
718
|
|
|
687
719
|
`evaluate` accepts the same options except `mask` (currently unsupported for evaluation output).
|
|
688
720
|
|
|
689
|
-
`validator_for` accepts the same options except `draft
|
|
721
|
+
`validator_for` accepts the same options except `draft:`. To pin a draft, use a draft-specific class such as `Draft7Validator.new`.
|
|
690
722
|
|
|
691
723
|
Valid draft symbols: `:draft4`, `:draft6`, `:draft7`, `:draft201909`, `:draft202012`.
|
|
692
724
|
|
|
693
725
|
## Performance
|
|
694
726
|
|
|
695
|
-
|
|
727
|
+
Compared with other Ruby validators:
|
|
696
728
|
|
|
697
729
|
- **28-148x** faster than `json_schemer` for complex schemas and large instances
|
|
698
730
|
- **200-567x** faster than `json-schema` where supported
|
|
699
731
|
- **7-130x** faster than `rj_schema` (RapidJSON/C++)
|
|
700
732
|
|
|
701
|
-
|
|
733
|
+
Full results and methodology are in [BENCHMARKS.md](https://github.com/Stranger6667/jsonschema/blob/master/crates/jsonschema-rb/BENCHMARKS.md).
|
|
702
734
|
|
|
703
735
|
### Compile-Time Validators
|
|
704
736
|
|
|
@@ -714,15 +746,15 @@ A complete extension with its build and test commands lives in
|
|
|
714
746
|
|
|
715
747
|
## Acknowledgements
|
|
716
748
|
|
|
717
|
-
|
|
749
|
+
The API design draws on the Python [`jsonschema`](https://github.com/python-jsonschema/jsonschema) package. Thanks to its maintainers and contributors.
|
|
718
750
|
|
|
719
751
|
## Support
|
|
720
752
|
|
|
721
|
-
|
|
753
|
+
Ask questions and suggest improvements in [GitHub Discussions](https://github.com/Stranger6667/jsonschema/discussions).
|
|
722
754
|
|
|
723
755
|
## Sponsorship
|
|
724
756
|
|
|
725
|
-
If you find `
|
|
757
|
+
If you find `jsonschema_rs` useful, please consider [sponsoring its development](https://github.com/sponsors/Stranger6667).
|
|
726
758
|
|
|
727
759
|
## Contributing
|
|
728
760
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/jsonschema/version.rb
CHANGED
data/sig/jsonschema.rbs
CHANGED
|
@@ -391,7 +391,8 @@ module JSONSchema
|
|
|
391
391
|
?registry: Registry?,
|
|
392
392
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
393
393
|
?email_options: EmailOptions?,
|
|
394
|
-
?http_options: HttpOptions
|
|
394
|
+
?http_options: HttpOptions?,
|
|
395
|
+
?offline: bool?
|
|
395
396
|
) -> Validator
|
|
396
397
|
|
|
397
398
|
# Create a map of validators for all sub-schemas in a JSON Schema.
|
|
@@ -408,7 +409,8 @@ module JSONSchema
|
|
|
408
409
|
?keywords: ::Hash[::String, untyped]?,
|
|
409
410
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
410
411
|
?email_options: EmailOptions?,
|
|
411
|
-
?http_options: HttpOptions
|
|
412
|
+
?http_options: HttpOptions?,
|
|
413
|
+
?offline: bool?
|
|
412
414
|
) -> ValidatorMap
|
|
413
415
|
|
|
414
416
|
# Bundle a JSON Schema into a Compound Schema Document.
|
|
@@ -421,7 +423,8 @@ module JSONSchema
|
|
|
421
423
|
?draft: draft?,
|
|
422
424
|
?retriever: (^(String) -> untyped)?,
|
|
423
425
|
?registry: Registry?,
|
|
424
|
-
?base_uri: String
|
|
426
|
+
?base_uri: String?,
|
|
427
|
+
?offline: bool?
|
|
425
428
|
) -> Hash[String, untyped]
|
|
426
429
|
|
|
427
430
|
# Dereference a JSON Schema by recursively replacing all $ref values
|
|
@@ -431,7 +434,8 @@ module JSONSchema
|
|
|
431
434
|
?draft: draft?,
|
|
432
435
|
?retriever: (^(String) -> untyped)?,
|
|
433
436
|
?registry: Registry?,
|
|
434
|
-
?base_uri: String
|
|
437
|
+
?base_uri: String?,
|
|
438
|
+
?offline: bool?
|
|
435
439
|
) -> untyped
|
|
436
440
|
|
|
437
441
|
# Detect the JSON Schema draft for a schema and return the corresponding validator class.
|
|
@@ -454,7 +458,8 @@ module JSONSchema
|
|
|
454
458
|
?registry: Registry?,
|
|
455
459
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
456
460
|
?email_options: EmailOptions?,
|
|
457
|
-
?http_options: HttpOptions
|
|
461
|
+
?http_options: HttpOptions?,
|
|
462
|
+
?offline: bool?
|
|
458
463
|
) -> bool
|
|
459
464
|
|
|
460
465
|
# One-off validation raising on error.
|
|
@@ -473,7 +478,8 @@ module JSONSchema
|
|
|
473
478
|
?registry: Registry?,
|
|
474
479
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
475
480
|
?email_options: EmailOptions?,
|
|
476
|
-
?http_options: HttpOptions
|
|
481
|
+
?http_options: HttpOptions?,
|
|
482
|
+
?offline: bool?
|
|
477
483
|
) -> nil
|
|
478
484
|
|
|
479
485
|
# Iterate validation errors. Returns Array when no block given, nil when block given.
|
|
@@ -492,7 +498,8 @@ module JSONSchema
|
|
|
492
498
|
?registry: Registry?,
|
|
493
499
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
494
500
|
?email_options: EmailOptions?,
|
|
495
|
-
?http_options: HttpOptions
|
|
501
|
+
?http_options: HttpOptions?,
|
|
502
|
+
?offline: bool?
|
|
496
503
|
) -> Array[ValidationError]
|
|
497
504
|
| (
|
|
498
505
|
untyped schema,
|
|
@@ -509,7 +516,8 @@ module JSONSchema
|
|
|
509
516
|
?registry: Registry?,
|
|
510
517
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
511
518
|
?email_options: EmailOptions?,
|
|
512
|
-
?http_options: HttpOptions
|
|
519
|
+
?http_options: HttpOptions?,
|
|
520
|
+
?offline: bool?
|
|
513
521
|
) { (ValidationError) -> void } -> nil
|
|
514
522
|
|
|
515
523
|
# One-off evaluation returning structured output.
|
|
@@ -527,7 +535,8 @@ module JSONSchema
|
|
|
527
535
|
?registry: Registry?,
|
|
528
536
|
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
529
537
|
?email_options: EmailOptions?,
|
|
530
|
-
?http_options: HttpOptions
|
|
538
|
+
?http_options: HttpOptions?,
|
|
539
|
+
?offline: bool?
|
|
531
540
|
) -> Evaluation
|
|
532
541
|
|
|
533
542
|
# Reusable JSON Schema validator.
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jsonschema_rs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.58.
|
|
4
|
+
version: 0.58.6
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dygalo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bigdecimal
|
|
@@ -56,7 +56,7 @@ metadata:
|
|
|
56
56
|
homepage_uri: https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-rb
|
|
57
57
|
source_code_uri: https://github.com/Stranger6667/jsonschema
|
|
58
58
|
changelog_uri: https://github.com/Stranger6667/jsonschema/blob/master/crates/jsonschema-rb/CHANGELOG.md
|
|
59
|
-
documentation_uri: https://github.com/Stranger6667/jsonschema/
|
|
59
|
+
documentation_uri: https://github.com/Stranger6667/jsonschema/blob/ruby-v0.58.6/crates/jsonschema-rb/README.md
|
|
60
60
|
bug_tracker_uri: https://github.com/Stranger6667/jsonschema/issues
|
|
61
61
|
funding_uri: https://github.com/sponsors/Stranger6667
|
|
62
62
|
rubygems_mfa_required: 'true'
|