jsonschema_rs 0.42.0-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 +7 -0
- data/CHANGELOG.md +8 -0
- data/LICENSE +21 -0
- data/MIGRATION.md +87 -0
- data/README.md +489 -0
- data/ext/jsonschema/extconf.rb +23 -0
- data/lib/jsonschema/3.2/jsonschema_rb.so +0 -0
- 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 +5 -0
- data/lib/jsonschema_rs.rb +10 -0
- data/sig/jsonschema.rbs +385 -0
- metadata +86 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 29e5bf1c85875f60a2e1d02f769b203839c377a3d72c63f8ae0aecf3c47ed7b3
|
|
4
|
+
data.tar.gz: 30e5f0a7e3e427eb2b1d4f5d34b995cf79c2b3fe06649b1a3d3a804d74f85e1f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 226a01d9b43a84e8e29cd2c373ff133a79fb0c9b7ff151d760040b5b8314a22efb873748f95e5a72afdcfd980099cedcdc8aed3004379d8920248912876c0b13
|
|
7
|
+
data.tar.gz: 921ca6bae055f06fbd00f9e680102b67ff69f87ee8b69e7f1cbb29235e02917b894b652a60676429e65831062259f063eb07968eef72356d255f48521dfe9a5c
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2026 Dmitry Dygalo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/MIGRATION.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Migrating from json_schemer
|
|
2
|
+
|
|
3
|
+
## Quick Reference
|
|
4
|
+
|
|
5
|
+
| json_schemer | jsonschema |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `JSONSchemer.schema(s)` | `JSONSchema.validator_for(s)` |
|
|
8
|
+
| `JSONSchemer.schema(s, meta_schema: 'draft7')` | `JSONSchema::Draft7Validator.new(s)` |
|
|
9
|
+
| `schemer.valid?(d)` | `validator.valid?(d)` |
|
|
10
|
+
| `schemer.validate(d)` | `validator.each_error(d)` |
|
|
11
|
+
| `schemer.validate!(d)` | `validator.validate!(d)` |
|
|
12
|
+
| `JSONSchemer.valid?(s, d)` | `JSONSchema.valid?(s, d)` |
|
|
13
|
+
| `JSONSchemer.valid_schema?(s)` | `JSONSchema::Meta.valid?(s)` |
|
|
14
|
+
| `error["data_pointer"]` | `error.instance_path_pointer` |
|
|
15
|
+
| `error["schema_pointer"]` | `error.schema_path_pointer` |
|
|
16
|
+
| `error["type"]` | `error.kind.name` |
|
|
17
|
+
| `error["error"]` | `error.message` |
|
|
18
|
+
| `ref_resolver: proc` | `retriever: proc` |
|
|
19
|
+
| `format: true` | `validate_formats: true` |
|
|
20
|
+
|
|
21
|
+
Draft-specific validators are also available: `JSONSchema::Draft7Validator.new(schema)`
|
|
22
|
+
|
|
23
|
+
## What Stays the Same
|
|
24
|
+
|
|
25
|
+
- JSON Schema documents work as-is
|
|
26
|
+
- `valid?` and `validate!` method names
|
|
27
|
+
- Custom format validators via `formats:` with the same proc syntax
|
|
28
|
+
- One-off validation: `JSONSchema.valid?(schema, data)`
|
|
29
|
+
|
|
30
|
+
## Error Objects
|
|
31
|
+
|
|
32
|
+
json_schemer returns hashes, jsonschema returns `ValidationError` objects:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
# json_schemer
|
|
36
|
+
error["data_pointer"] # => "/foo/bar"
|
|
37
|
+
error["schema_pointer"] # => "/properties/foo/minimum"
|
|
38
|
+
error["type"] # => "minimum"
|
|
39
|
+
error["error"] # => "value is less than 10"
|
|
40
|
+
|
|
41
|
+
# jsonschema
|
|
42
|
+
error.instance_path # => ["foo", "bar"]
|
|
43
|
+
error.instance_path_pointer # => "/foo/bar" (same format as data_pointer)
|
|
44
|
+
error.schema_path # => ["properties", "foo", "minimum"]
|
|
45
|
+
error.schema_path_pointer # => "/properties/foo/minimum"
|
|
46
|
+
error.kind.name # => "minimum"
|
|
47
|
+
error.message # => "value is less than 10"
|
|
48
|
+
|
|
49
|
+
# Need a hash? Use to_h on error kind
|
|
50
|
+
error.kind.to_h # => { "name" => "minimum", "value" => { "limit" => 10 } }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Reference Resolution
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
# json_schemer
|
|
57
|
+
JSONSchemer.schema(schema, ref_resolver: refs.to_proc)
|
|
58
|
+
|
|
59
|
+
# jsonschema — retriever
|
|
60
|
+
JSONSchema.validator_for(schema, retriever: ->(uri) { fetch_schema(uri) })
|
|
61
|
+
|
|
62
|
+
# jsonschema — registry
|
|
63
|
+
registry = JSONSchema::Registry.new([["http://example.com/s", sub_schema]])
|
|
64
|
+
JSONSchema.validator_for(schema, registry: registry)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## What You Gain
|
|
68
|
+
|
|
69
|
+
- **Structured output** — `evaluate` API with flag, list, and hierarchical output formats
|
|
70
|
+
- **Custom keywords** — extend JSON Schema with domain-specific validation rules
|
|
71
|
+
- **Error masking** — hide sensitive data in error messages with `mask:`
|
|
72
|
+
- **Regex engine configuration** — choose between fancy-regex (default) and linear-time regex
|
|
73
|
+
- **Email validation options** — fine-grained control over email format validation
|
|
74
|
+
|
|
75
|
+
## Not Supported
|
|
76
|
+
|
|
77
|
+
- `insert_property_defaults` — jsonschema is a validator, not a data transformer
|
|
78
|
+
- OpenAPI document parsing — use a dedicated OpenAPI library
|
|
79
|
+
|
|
80
|
+
## Migration Checklist
|
|
81
|
+
|
|
82
|
+
- [ ] Replace `JSONSchemer.schema` with `JSONSchema.validator_for`
|
|
83
|
+
- [ ] Replace `validate` (error iteration) with `each_error`
|
|
84
|
+
- [ ] Replace `ref_resolver:` with `retriever:` or use `Registry`
|
|
85
|
+
- [ ] Replace `format: true` with `validate_formats: true`
|
|
86
|
+
- [ ] Replace `meta_schema: 'draft7'` with `JSONSchema::Draft7Validator.new(s)` or `draft: :draft7` on one-off functions
|
|
87
|
+
- [ ] Update error handling from hash access to `ValidationError` attributes
|
data/README.md
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
# jsonschema_rs
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Stranger6667/jsonschema/actions)
|
|
4
|
+
[](https://rubygems.org/gems/jsonschema_rs)
|
|
5
|
+
[](https://rubygems.org/gems/jsonschema_rs)
|
|
6
|
+
[<img alt="Supported Dialects" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Frust-jsonschema%2Fsupported_versions.json&style=flat-square">](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
7
|
+
|
|
8
|
+
A high-performance JSON Schema validator for Ruby.
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
require 'jsonschema_rs'
|
|
12
|
+
|
|
13
|
+
schema = { "maxLength" => 5 }
|
|
14
|
+
instance = "foo"
|
|
15
|
+
|
|
16
|
+
# One-off validation
|
|
17
|
+
JSONSchema.valid?(schema, instance) # => true
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
JSONSchema.validate!(schema, "incorrect")
|
|
21
|
+
rescue JSONSchema::ValidationError => e
|
|
22
|
+
puts e.message # => "\"incorrect\" is longer than 5 characters"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Build & reuse (faster)
|
|
26
|
+
validator = JSONSchema.validator_for(schema)
|
|
27
|
+
|
|
28
|
+
# Iterate over errors
|
|
29
|
+
validator.each_error(instance) do |error|
|
|
30
|
+
puts "Error: #{error.message}"
|
|
31
|
+
puts "Location: #{error.instance_path}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Boolean result
|
|
35
|
+
validator.valid?(instance) # => true
|
|
36
|
+
|
|
37
|
+
# Structured output (JSON Schema Output v1)
|
|
38
|
+
evaluation = validator.evaluate(instance)
|
|
39
|
+
evaluation.annotations.each do |ann|
|
|
40
|
+
puts "Annotation at #{ann[:schemaLocation]}: #{ann[:annotations]}"
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> **Migrating from `json_schemer`?** See the [migration guide](MIGRATION.md).
|
|
45
|
+
|
|
46
|
+
## Highlights
|
|
47
|
+
|
|
48
|
+
- 📚 Full support for popular JSON Schema drafts
|
|
49
|
+
- 🌐 Remote reference fetching (network/file)
|
|
50
|
+
- 🔧 Custom keywords and format validators
|
|
51
|
+
- ✨ Meta-schema validation for schema documents
|
|
52
|
+
- ♦️ Supports Ruby 3.2, 3.4 and 4.0
|
|
53
|
+
|
|
54
|
+
### Supported drafts
|
|
55
|
+
|
|
56
|
+
The following drafts are supported:
|
|
57
|
+
|
|
58
|
+
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
59
|
+
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
60
|
+
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
61
|
+
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
62
|
+
- [](https://bowtie.report/#/implementations/rust-jsonschema)
|
|
63
|
+
|
|
64
|
+
You can check the current status on the [Bowtie Report](https://bowtie.report/#/implementations/rust-jsonschema).
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
Add to your Gemfile:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
gem 'jsonschema_rs'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Pre-built native gems are available for:
|
|
75
|
+
|
|
76
|
+
- **Linux**: `x86_64`, `aarch64` (glibc and musl)
|
|
77
|
+
- **macOS**: `x86_64`, `arm64`
|
|
78
|
+
- **Windows**: `x64` (mingw-ucrt)
|
|
79
|
+
|
|
80
|
+
If no pre-built gem is available for your platform, it will be compiled from source during installation. You'll need:
|
|
81
|
+
- Ruby 3.2+
|
|
82
|
+
- Rust toolchain ([rustup](https://rustup.rs/))
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
### Reusable validators
|
|
87
|
+
|
|
88
|
+
For validating multiple instances against the same schema, create a reusable validator.
|
|
89
|
+
`validator_for` automatically detects the draft version from the `$schema` keyword in the schema:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
validator = JSONSchema.validator_for({
|
|
93
|
+
"type" => "object",
|
|
94
|
+
"properties" => {
|
|
95
|
+
"name" => { "type" => "string" },
|
|
96
|
+
"age" => { "type" => "integer", "minimum" => 0 }
|
|
97
|
+
},
|
|
98
|
+
"required" => ["name"]
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
validator.valid?({ "name" => "Alice", "age" => 30 }) # => true
|
|
102
|
+
validator.valid?({ "age" => 30 }) # => false
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
You can use draft-specific validators for different JSON Schema versions:
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
validator = JSONSchema::Draft7Validator.new(schema)
|
|
109
|
+
|
|
110
|
+
# Available: Draft4Validator, Draft6Validator, Draft7Validator,
|
|
111
|
+
# Draft201909Validator, Draft202012Validator
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Custom format validators
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
phone_format = ->(value) { value.match?(/^\+?[1-9]\d{1,14}$/) }
|
|
118
|
+
|
|
119
|
+
validator = JSONSchema.validator_for(
|
|
120
|
+
{ "type" => "string", "format" => "phone" },
|
|
121
|
+
validate_formats: true,
|
|
122
|
+
formats: { "phone" => phone_format }
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Custom keyword validators
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
class EvenValidator
|
|
130
|
+
def initialize(parent_schema, value, schema_path)
|
|
131
|
+
@enabled = value
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def validate(instance)
|
|
135
|
+
return unless @enabled && instance.is_a?(Integer)
|
|
136
|
+
raise "#{instance} is not even" if instance.odd?
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
validator = JSONSchema.validator_for(
|
|
141
|
+
{ "type" => "integer", "even" => true },
|
|
142
|
+
keywords: { "even" => EvenValidator }
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Each custom keyword class must implement:
|
|
147
|
+
- `initialize(parent_schema, value, schema_path)` - called during schema compilation
|
|
148
|
+
- `validate(instance)` - raise on failure, return normally on success
|
|
149
|
+
|
|
150
|
+
### Structured evaluation output
|
|
151
|
+
|
|
152
|
+
When you need more than a boolean result, use the `evaluate` API to access the JSON Schema Output v1 formats:
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
schema = {
|
|
156
|
+
"type" => "object",
|
|
157
|
+
"properties" => {
|
|
158
|
+
"name" => { "type" => "string" },
|
|
159
|
+
"age" => { "type" => "integer" }
|
|
160
|
+
},
|
|
161
|
+
"required" => ["name"]
|
|
162
|
+
}
|
|
163
|
+
validator = JSONSchema.validator_for(schema)
|
|
164
|
+
|
|
165
|
+
evaluation = validator.evaluate({ "age" => "not_an_integer" })
|
|
166
|
+
|
|
167
|
+
evaluation.valid? # => false
|
|
168
|
+
|
|
169
|
+
# Flag output (simplest)
|
|
170
|
+
evaluation.flag
|
|
171
|
+
# => { "valid" => false }
|
|
172
|
+
|
|
173
|
+
# List output (flat)
|
|
174
|
+
evaluation.list
|
|
175
|
+
# => { "valid" => false, "details" => [
|
|
176
|
+
# { "valid" => false, "evaluationPath" => "", "instanceLocation" => "", "schemaLocation" => "" },
|
|
177
|
+
# { "valid" => false, "evaluationPath" => "/required", "instanceLocation" => "", "schemaLocation" => "/required",
|
|
178
|
+
# "errors" => { "required" => "\"name\" is a required property" } },
|
|
179
|
+
# ...
|
|
180
|
+
# ] }
|
|
181
|
+
|
|
182
|
+
# Hierarchical output (nested tree following schema structure)
|
|
183
|
+
evaluation.hierarchical
|
|
184
|
+
# => { "valid" => false, "evaluationPath" => "", "instanceLocation" => "", "schemaLocation" => "",
|
|
185
|
+
# "details" => [ ... ] }
|
|
186
|
+
|
|
187
|
+
# Collected errors across all nodes
|
|
188
|
+
evaluation.errors
|
|
189
|
+
# => [{ "schemaLocation" => "/required", "instanceLocation" => "",
|
|
190
|
+
# "absoluteKeywordLocation" => nil, "error" => "\"name\" is a required property" }, ...]
|
|
191
|
+
|
|
192
|
+
# Collected annotations
|
|
193
|
+
evaluation.annotations
|
|
194
|
+
# => [{ "schemaLocation" => "/properties", "instanceLocation" => "",
|
|
195
|
+
# "absoluteKeywordLocation" => nil, "annotations" => ["age"] }]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Meta-Schema Validation
|
|
199
|
+
|
|
200
|
+
Validate that a JSON Schema document is itself valid:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
JSONSchema::Meta.valid?({ "type" => "string" }) # => true
|
|
204
|
+
JSONSchema::Meta.valid?({ "type" => "invalid_type" }) # => false
|
|
205
|
+
|
|
206
|
+
begin
|
|
207
|
+
JSONSchema::Meta.validate!({ "type" => 123 })
|
|
208
|
+
rescue JSONSchema::ValidationError => e
|
|
209
|
+
e.message # => "123 is not valid under any of the schemas listed in the 'anyOf' keyword"
|
|
210
|
+
end
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## External References
|
|
214
|
+
|
|
215
|
+
By default, `jsonschema` resolves HTTP references and file references from the local file system. You can implement a custom retriever to handle external references:
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
schemas = {
|
|
219
|
+
"https://example.com/person.json" => {
|
|
220
|
+
"type" => "object",
|
|
221
|
+
"properties" => {
|
|
222
|
+
"name" => { "type" => "string" },
|
|
223
|
+
"age" => { "type" => "integer" }
|
|
224
|
+
},
|
|
225
|
+
"required" => ["name", "age"]
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
retriever = ->(uri) { schemas[uri] }
|
|
230
|
+
|
|
231
|
+
schema = { "$ref" => "https://example.com/person.json" }
|
|
232
|
+
validator = JSONSchema.validator_for(schema, retriever: retriever)
|
|
233
|
+
|
|
234
|
+
validator.valid?({ "name" => "Alice", "age" => 30 }) # => true
|
|
235
|
+
validator.valid?({ "name" => "Bob" }) # => false (missing "age")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Schema Registry
|
|
239
|
+
|
|
240
|
+
For applications that frequently use the same schemas, create a registry to store and reference them:
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
registry = JSONSchema::Registry.new([
|
|
244
|
+
["https://example.com/address.json", {
|
|
245
|
+
"type" => "object",
|
|
246
|
+
"properties" => {
|
|
247
|
+
"street" => { "type" => "string" },
|
|
248
|
+
"city" => { "type" => "string" }
|
|
249
|
+
}
|
|
250
|
+
}],
|
|
251
|
+
["https://example.com/person.json", {
|
|
252
|
+
"type" => "object",
|
|
253
|
+
"properties" => {
|
|
254
|
+
"name" => { "type" => "string" },
|
|
255
|
+
"address" => { "$ref" => "https://example.com/address.json" }
|
|
256
|
+
}
|
|
257
|
+
}]
|
|
258
|
+
])
|
|
259
|
+
|
|
260
|
+
validator = JSONSchema.validator_for(
|
|
261
|
+
{ "$ref" => "https://example.com/person.json" },
|
|
262
|
+
registry: registry
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
validator.valid?({
|
|
266
|
+
"name" => "John",
|
|
267
|
+
"address" => { "street" => "Main St", "city" => "Boston" }
|
|
268
|
+
}) # => true
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
The registry also accepts `draft:` and `retriever:` options:
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
registry = JSONSchema::Registry.new(
|
|
275
|
+
[["https://example.com/person.json", schemas["https://example.com/person.json"]]],
|
|
276
|
+
draft: :draft7,
|
|
277
|
+
retriever: retriever
|
|
278
|
+
)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Regular Expression Configuration
|
|
282
|
+
|
|
283
|
+
When validating schemas with regex patterns (in `pattern` or `patternProperties`), you can configure the underlying regex engine:
|
|
284
|
+
|
|
285
|
+
```ruby
|
|
286
|
+
# Default fancy-regex engine with backtracking limits
|
|
287
|
+
# (supports lookaround and backreferences but needs protection against DoS)
|
|
288
|
+
validator = JSONSchema.validator_for(
|
|
289
|
+
{ "type" => "string", "pattern" => "^(a+)+$" },
|
|
290
|
+
pattern_options: JSONSchema::FancyRegexOptions.new(backtrack_limit: 10_000)
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# Standard regex engine for guaranteed linear-time matching
|
|
294
|
+
# (prevents regex DoS attacks but supports fewer features)
|
|
295
|
+
validator = JSONSchema.validator_for(
|
|
296
|
+
{ "type" => "string", "pattern" => "^a+$" },
|
|
297
|
+
pattern_options: JSONSchema::RegexOptions.new
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Both engines support memory usage configuration
|
|
301
|
+
validator = JSONSchema.validator_for(
|
|
302
|
+
{ "type" => "string", "pattern" => "^a+$" },
|
|
303
|
+
pattern_options: JSONSchema::RegexOptions.new(
|
|
304
|
+
size_limit: 1024 * 1024, # Maximum compiled pattern size
|
|
305
|
+
dfa_size_limit: 10240 # Maximum DFA cache size
|
|
306
|
+
)
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
The available options:
|
|
311
|
+
|
|
312
|
+
- `FancyRegexOptions`: Default engine with lookaround and backreferences support
|
|
313
|
+
|
|
314
|
+
- `backtrack_limit`: Maximum backtracking steps
|
|
315
|
+
- `size_limit`: Maximum compiled regex size in bytes
|
|
316
|
+
- `dfa_size_limit`: Maximum DFA cache size in bytes
|
|
317
|
+
|
|
318
|
+
- `RegexOptions`: Safer engine with linear-time guarantee
|
|
319
|
+
|
|
320
|
+
- `size_limit`: Maximum compiled regex size in bytes
|
|
321
|
+
- `dfa_size_limit`: Maximum DFA cache size in bytes
|
|
322
|
+
|
|
323
|
+
This configuration is crucial when working with untrusted schemas where attackers might craft malicious regex patterns.
|
|
324
|
+
|
|
325
|
+
## Email Format Configuration
|
|
326
|
+
|
|
327
|
+
When validating email addresses using `{"format": "email"}`, you can customize the validation behavior:
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
# Require a top-level domain (reject "user@localhost")
|
|
331
|
+
validator = JSONSchema.validator_for(
|
|
332
|
+
{ "format" => "email", "type" => "string" },
|
|
333
|
+
validate_formats: true,
|
|
334
|
+
email_options: JSONSchema::EmailOptions.new(require_tld: true)
|
|
335
|
+
)
|
|
336
|
+
validator.valid?("user@localhost") # => false
|
|
337
|
+
validator.valid?("user@example.com") # => true
|
|
338
|
+
|
|
339
|
+
# Disallow IP address literals and display names
|
|
340
|
+
validator = JSONSchema.validator_for(
|
|
341
|
+
{ "format" => "email", "type" => "string" },
|
|
342
|
+
validate_formats: true,
|
|
343
|
+
email_options: JSONSchema::EmailOptions.new(
|
|
344
|
+
allow_domain_literal: false, # Reject "user@[127.0.0.1]"
|
|
345
|
+
allow_display_text: false # Reject "Name <user@example.com>"
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# Require minimum domain segments
|
|
350
|
+
validator = JSONSchema.validator_for(
|
|
351
|
+
{ "format" => "email", "type" => "string" },
|
|
352
|
+
validate_formats: true,
|
|
353
|
+
email_options: JSONSchema::EmailOptions.new(minimum_sub_domains: 3) # e.g., user@sub.example.com
|
|
354
|
+
)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Available options:
|
|
358
|
+
|
|
359
|
+
- `require_tld`: Require a top-level domain (e.g., reject "user@localhost")
|
|
360
|
+
- `allow_domain_literal`: Allow IP address literals like "user@[127.0.0.1]" (default: true)
|
|
361
|
+
- `allow_display_text`: Allow display names like "Name <user@example.com>" (default: true)
|
|
362
|
+
- `minimum_sub_domains`: Minimum number of domain segments required
|
|
363
|
+
|
|
364
|
+
## Error Handling
|
|
365
|
+
|
|
366
|
+
`jsonschema` provides detailed validation errors through the `ValidationError` class:
|
|
367
|
+
|
|
368
|
+
```ruby
|
|
369
|
+
schema = { "type" => "string", "maxLength" => 5 }
|
|
370
|
+
|
|
371
|
+
begin
|
|
372
|
+
JSONSchema.validate!(schema, "too long")
|
|
373
|
+
rescue JSONSchema::ValidationError => error
|
|
374
|
+
# Basic error information
|
|
375
|
+
error.message # => '"too long" is longer than 5 characters'
|
|
376
|
+
error.verbose_message # => Full context with schema path and instance
|
|
377
|
+
error.instance_path # => Location in the instance that failed
|
|
378
|
+
error.schema_path # => Location in the schema that failed
|
|
379
|
+
|
|
380
|
+
# Detailed error information via `kind`
|
|
381
|
+
error.kind.name # => "maxLength"
|
|
382
|
+
error.kind.value # => { "limit" => 5 }
|
|
383
|
+
error.kind.to_h # => { "name" => "maxLength", "value" => { "limit" => 5 } }
|
|
384
|
+
end
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Error Kind Properties
|
|
388
|
+
|
|
389
|
+
Each error has a `kind` property with convenient accessors:
|
|
390
|
+
|
|
391
|
+
```ruby
|
|
392
|
+
JSONSchema.each_error({ "minimum" => 5 }, 3).each do |error|
|
|
393
|
+
error.kind.name # => "minimum"
|
|
394
|
+
error.kind.value # => { "limit" => 5 }
|
|
395
|
+
error.kind.to_h # => { "name" => "minimum", "value" => { "limit" => 5 } }
|
|
396
|
+
error.kind.to_s # => "minimum"
|
|
397
|
+
end
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Error Message Masking
|
|
401
|
+
|
|
402
|
+
When working with sensitive data, you can mask instance values in error messages:
|
|
403
|
+
|
|
404
|
+
```ruby
|
|
405
|
+
schema = {
|
|
406
|
+
"type" => "object",
|
|
407
|
+
"properties" => {
|
|
408
|
+
"password" => { "type" => "string", "minLength" => 8 },
|
|
409
|
+
"api_key" => { "type" => "string", "pattern" => "^[A-Z0-9]{32}$" }
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
validator = JSONSchema.validator_for(schema, mask: "[REDACTED]")
|
|
414
|
+
|
|
415
|
+
begin
|
|
416
|
+
validator.validate!({ "password" => "123", "api_key" => "secret_key_123" })
|
|
417
|
+
rescue JSONSchema::ValidationError => exc
|
|
418
|
+
puts exc.message
|
|
419
|
+
# => '[REDACTED] does not match "^[A-Z0-9]{32}$"'
|
|
420
|
+
puts exc.verbose_message
|
|
421
|
+
# => '[REDACTED] does not match "^[A-Z0-9]{32}$"\n\nFailed validating...\nOn instance["api_key"]:\n [REDACTED]'
|
|
422
|
+
end
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Exception Classes
|
|
426
|
+
|
|
427
|
+
- **`JSONSchema::ValidationError`** - raised on validation failure
|
|
428
|
+
- `message`, `verbose_message`, `instance_path`, `schema_path`, `evaluation_path`, `kind`, `instance`
|
|
429
|
+
- JSON Pointer helpers: `instance_path_pointer`, `schema_path_pointer`, `evaluation_path_pointer`
|
|
430
|
+
- **`JSONSchema::ReferencingError`** - raised when `$ref` cannot be resolved
|
|
431
|
+
|
|
432
|
+
## Options Reference
|
|
433
|
+
|
|
434
|
+
One-off validation methods (`valid?`, `validate!`, `each_error`, `evaluate`) accept these keyword arguments:
|
|
435
|
+
|
|
436
|
+
```ruby
|
|
437
|
+
JSONSchema.valid?(schema, instance,
|
|
438
|
+
draft: :draft7, # Specific draft version (symbol)
|
|
439
|
+
validate_formats: true, # Enable format validation (default: false)
|
|
440
|
+
ignore_unknown_formats: true, # Don't error on unknown formats (default: true)
|
|
441
|
+
base_uri: "https://example.com", # Base URI for reference resolution
|
|
442
|
+
mask: "[REDACTED]", # Mask sensitive data in error messages
|
|
443
|
+
retriever: ->(uri) { ... }, # Custom schema retriever for $ref
|
|
444
|
+
formats: { "name" => proc }, # Custom format validators
|
|
445
|
+
keywords: { "name" => Klass }, # Custom keyword validators
|
|
446
|
+
registry: registry, # Pre-registered schemas
|
|
447
|
+
pattern_options: opts, # RegexOptions or FancyRegexOptions
|
|
448
|
+
email_options: opts, # EmailOptions
|
|
449
|
+
http_options: opts # HttpOptions
|
|
450
|
+
)
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
`evaluate` accepts the same options except `mask` (currently unsupported for evaluation output).
|
|
454
|
+
|
|
455
|
+
`validator_for` accepts the same options except `draft:` — use draft-specific validators (`Draft7Validator.new`, etc.) to pin a draft version.
|
|
456
|
+
|
|
457
|
+
Valid draft symbols: `:draft4`, `:draft6`, `:draft7`, `:draft201909`, `:draft202012`.
|
|
458
|
+
|
|
459
|
+
## Performance
|
|
460
|
+
|
|
461
|
+
`jsonschema` is designed for high performance, outperforming other Ruby JSON Schema validators in most scenarios:
|
|
462
|
+
|
|
463
|
+
- **26-141x** faster than `json_schemer` for complex schemas and large instances
|
|
464
|
+
- **174-535x** faster than `json-schema` where supported
|
|
465
|
+
- **7-125x** faster than `rj_schema` (RapidJSON/C++)
|
|
466
|
+
|
|
467
|
+
For detailed benchmarks, see our [full performance comparison](https://github.com/Stranger6667/jsonschema/blob/master/crates/jsonschema-rb/BENCHMARKS.md).
|
|
468
|
+
|
|
469
|
+
**Tips:** Reuse validators. Use `valid?` for boolean checks (short-circuits on first error).
|
|
470
|
+
|
|
471
|
+
## Acknowledgements
|
|
472
|
+
|
|
473
|
+
This library draws API design inspiration from the Python [`jsonschema`](https://github.com/python-jsonschema/jsonschema) package. We're grateful to the Python `jsonschema` maintainers and contributors for their pioneering work in JSON Schema validation.
|
|
474
|
+
|
|
475
|
+
## Support
|
|
476
|
+
|
|
477
|
+
If you have questions, need help, or want to suggest improvements, please use [GitHub Discussions](https://github.com/Stranger6667/jsonschema/discussions).
|
|
478
|
+
|
|
479
|
+
## Sponsorship
|
|
480
|
+
|
|
481
|
+
If you find `jsonschema` useful, please consider [sponsoring its development](https://github.com/sponsors/Stranger6667).
|
|
482
|
+
|
|
483
|
+
## Contributing
|
|
484
|
+
|
|
485
|
+
See [CONTRIBUTING.md](https://github.com/Stranger6667/jsonschema/blob/master/CONTRIBUTING.md) for details.
|
|
486
|
+
|
|
487
|
+
## License
|
|
488
|
+
|
|
489
|
+
Licensed under [MIT License](https://github.com/Stranger6667/jsonschema/blob/master/LICENSE).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
require "rb_sys/mkmf"
|
|
5
|
+
|
|
6
|
+
create_rust_makefile("jsonschema/jsonschema_rb") do |r|
|
|
7
|
+
r.auto_install_rust_toolchain = false
|
|
8
|
+
|
|
9
|
+
musl_target =
|
|
10
|
+
ENV["CARGO_BUILD_TARGET"]&.include?("musl") ||
|
|
11
|
+
File.exist?("/etc/alpine-release") ||
|
|
12
|
+
begin
|
|
13
|
+
`ldd --version 2>&1` =~ /musl/
|
|
14
|
+
rescue StandardError
|
|
15
|
+
false
|
|
16
|
+
end ||
|
|
17
|
+
`rustc -vV 2>/dev/null`[/host: (.+)/, 1]&.include?("musl")
|
|
18
|
+
|
|
19
|
+
if musl_target
|
|
20
|
+
# Disable static CRT on musl.
|
|
21
|
+
r.extra_rustflags = ["-C", "target-feature=-crt-static"]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/sig/jsonschema.rbs
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# Type definitions for jsonschema gem
|
|
2
|
+
# High-performance JSON Schema validation for Ruby
|
|
3
|
+
|
|
4
|
+
module JSONSchema
|
|
5
|
+
VERSION: String
|
|
6
|
+
|
|
7
|
+
# Valid draft version symbols
|
|
8
|
+
type draft = :draft4 | :draft6 | :draft7 | :draft201909 | :draft202012
|
|
9
|
+
|
|
10
|
+
# Create a validator with auto-detected draft version.
|
|
11
|
+
#
|
|
12
|
+
# @param schema The JSON Schema (Hash or JSON string)
|
|
13
|
+
# @param validate_formats Enable format validation
|
|
14
|
+
# @param ignore_unknown_formats Ignore unknown formats
|
|
15
|
+
# @param base_uri Base URI for reference resolution
|
|
16
|
+
# @param retriever Custom schema retriever proc
|
|
17
|
+
# @param mask Mask sensitive data in error messages
|
|
18
|
+
# @param formats Custom format validators (Hash of format_name => proc)
|
|
19
|
+
# @param keywords Custom keyword validators (Hash of keyword_name => class)
|
|
20
|
+
def self.validator_for: (
|
|
21
|
+
untyped schema,
|
|
22
|
+
?validate_formats: bool?,
|
|
23
|
+
?ignore_unknown_formats: bool?,
|
|
24
|
+
?base_uri: String?,
|
|
25
|
+
?retriever: (^(String) -> untyped)?,
|
|
26
|
+
?mask: String?,
|
|
27
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
28
|
+
?keywords: Hash[String, Class]?,
|
|
29
|
+
?registry: Registry?,
|
|
30
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
31
|
+
?email_options: EmailOptions?,
|
|
32
|
+
?http_options: HttpOptions?
|
|
33
|
+
) -> Validator
|
|
34
|
+
|
|
35
|
+
# One-off validation returning boolean.
|
|
36
|
+
def self.valid?: (
|
|
37
|
+
untyped schema,
|
|
38
|
+
untyped instance,
|
|
39
|
+
?draft: draft?,
|
|
40
|
+
?validate_formats: bool?,
|
|
41
|
+
?ignore_unknown_formats: bool?,
|
|
42
|
+
?base_uri: String?,
|
|
43
|
+
?retriever: (^(String) -> untyped)?,
|
|
44
|
+
?mask: String?,
|
|
45
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
46
|
+
?keywords: Hash[String, Class]?,
|
|
47
|
+
?registry: Registry?,
|
|
48
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
49
|
+
?email_options: EmailOptions?,
|
|
50
|
+
?http_options: HttpOptions?
|
|
51
|
+
) -> bool
|
|
52
|
+
|
|
53
|
+
# One-off validation raising on error.
|
|
54
|
+
def self.validate!: (
|
|
55
|
+
untyped schema,
|
|
56
|
+
untyped instance,
|
|
57
|
+
?draft: draft?,
|
|
58
|
+
?validate_formats: bool?,
|
|
59
|
+
?ignore_unknown_formats: bool?,
|
|
60
|
+
?base_uri: String?,
|
|
61
|
+
?retriever: (^(String) -> untyped)?,
|
|
62
|
+
?mask: String?,
|
|
63
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
64
|
+
?keywords: Hash[String, Class]?,
|
|
65
|
+
?registry: Registry?,
|
|
66
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
67
|
+
?email_options: EmailOptions?,
|
|
68
|
+
?http_options: HttpOptions?
|
|
69
|
+
) -> nil
|
|
70
|
+
|
|
71
|
+
# Iterate validation errors. Returns Array when no block given, nil when block given.
|
|
72
|
+
def self.each_error: (
|
|
73
|
+
untyped schema,
|
|
74
|
+
untyped instance,
|
|
75
|
+
?draft: draft?,
|
|
76
|
+
?validate_formats: bool?,
|
|
77
|
+
?ignore_unknown_formats: bool?,
|
|
78
|
+
?base_uri: String?,
|
|
79
|
+
?retriever: (^(String) -> untyped)?,
|
|
80
|
+
?mask: String?,
|
|
81
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
82
|
+
?keywords: Hash[String, Class]?,
|
|
83
|
+
?registry: Registry?,
|
|
84
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
85
|
+
?email_options: EmailOptions?,
|
|
86
|
+
?http_options: HttpOptions?
|
|
87
|
+
) -> Array[ValidationError]
|
|
88
|
+
| (
|
|
89
|
+
untyped schema,
|
|
90
|
+
untyped instance,
|
|
91
|
+
?draft: draft?,
|
|
92
|
+
?validate_formats: bool?,
|
|
93
|
+
?ignore_unknown_formats: bool?,
|
|
94
|
+
?base_uri: String?,
|
|
95
|
+
?retriever: (^(String) -> untyped)?,
|
|
96
|
+
?mask: String?,
|
|
97
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
98
|
+
?keywords: Hash[String, Class]?,
|
|
99
|
+
?registry: Registry?,
|
|
100
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
101
|
+
?email_options: EmailOptions?,
|
|
102
|
+
?http_options: HttpOptions?
|
|
103
|
+
) { (ValidationError) -> void } -> nil
|
|
104
|
+
|
|
105
|
+
# One-off evaluation returning structured output.
|
|
106
|
+
def self.evaluate: (
|
|
107
|
+
untyped schema,
|
|
108
|
+
untyped instance,
|
|
109
|
+
?draft: draft?,
|
|
110
|
+
?validate_formats: bool?,
|
|
111
|
+
?ignore_unknown_formats: bool?,
|
|
112
|
+
?base_uri: String?,
|
|
113
|
+
?retriever: (^(String) -> untyped)?,
|
|
114
|
+
?formats: Hash[String, ^(String) -> bool]?,
|
|
115
|
+
?keywords: Hash[String, Class]?,
|
|
116
|
+
?registry: Registry?,
|
|
117
|
+
?pattern_options: (RegexOptions | FancyRegexOptions)?,
|
|
118
|
+
?email_options: EmailOptions?,
|
|
119
|
+
?http_options: HttpOptions?
|
|
120
|
+
) -> Evaluation
|
|
121
|
+
|
|
122
|
+
# Reusable JSON Schema validator.
|
|
123
|
+
private
|
|
124
|
+
class Validator
|
|
125
|
+
# Fast validation returning boolean.
|
|
126
|
+
def valid?: (untyped instance) -> bool
|
|
127
|
+
|
|
128
|
+
# Validate and raise on first error.
|
|
129
|
+
def validate!: (untyped instance) -> nil
|
|
130
|
+
|
|
131
|
+
# Iterate validation errors. Returns Array when no block given, nil when block given.
|
|
132
|
+
def each_error: (untyped instance) -> Array[ValidationError]
|
|
133
|
+
| (untyped instance) { (ValidationError) -> void } -> nil
|
|
134
|
+
|
|
135
|
+
# Evaluate instance and return structured output.
|
|
136
|
+
def evaluate: (untyped instance) -> Evaluation
|
|
137
|
+
|
|
138
|
+
def inspect: () -> String
|
|
139
|
+
end
|
|
140
|
+
public
|
|
141
|
+
|
|
142
|
+
# JSON Schema Draft 4 validator.
|
|
143
|
+
class Draft4Validator < Validator
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# JSON Schema Draft 6 validator.
|
|
147
|
+
class Draft6Validator < Validator
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# JSON Schema Draft 7 validator.
|
|
151
|
+
class Draft7Validator < Validator
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# JSON Schema Draft 2019-09 validator.
|
|
155
|
+
class Draft201909Validator < Validator
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# JSON Schema Draft 2020-12 validator.
|
|
159
|
+
class Draft202012Validator < Validator
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Validation error with detailed information.
|
|
163
|
+
class ValidationError < StandardError
|
|
164
|
+
# Brief error message.
|
|
165
|
+
attr_reader message: String
|
|
166
|
+
|
|
167
|
+
# Detailed error message with full context.
|
|
168
|
+
attr_reader verbose_message: String
|
|
169
|
+
|
|
170
|
+
# Path to the failing instance location.
|
|
171
|
+
attr_reader instance_path: Array[String | Integer]
|
|
172
|
+
|
|
173
|
+
# Path to the failing schema location.
|
|
174
|
+
attr_reader schema_path: Array[String | Integer]
|
|
175
|
+
|
|
176
|
+
# Evaluation path.
|
|
177
|
+
attr_reader evaluation_path: Array[String | Integer]
|
|
178
|
+
|
|
179
|
+
# The specific kind of validation error.
|
|
180
|
+
attr_reader kind: ValidationErrorKind
|
|
181
|
+
|
|
182
|
+
# The failing instance value.
|
|
183
|
+
attr_reader instance: untyped
|
|
184
|
+
|
|
185
|
+
def initialize: (
|
|
186
|
+
message: String,
|
|
187
|
+
?verbose_message: String?,
|
|
188
|
+
?instance_path: Array[String | Integer],
|
|
189
|
+
?schema_path: Array[String | Integer],
|
|
190
|
+
?evaluation_path: Array[String | Integer],
|
|
191
|
+
?kind: ValidationErrorKind?,
|
|
192
|
+
?instance: untyped
|
|
193
|
+
) -> void
|
|
194
|
+
|
|
195
|
+
def to_s: () -> String
|
|
196
|
+
def inspect: () -> String
|
|
197
|
+
|
|
198
|
+
# Compare two validation errors by message, schema_path, and instance_path.
|
|
199
|
+
def ==: (untyped other) -> bool
|
|
200
|
+
alias eql? ==
|
|
201
|
+
|
|
202
|
+
# Hash code based on message, schema_path, and instance_path.
|
|
203
|
+
def hash: () -> Integer
|
|
204
|
+
|
|
205
|
+
# Convert instance_path to JSON Pointer format (RFC 6901).
|
|
206
|
+
def instance_path_pointer: () -> String
|
|
207
|
+
|
|
208
|
+
# Convert schema_path to JSON Pointer format (RFC 6901).
|
|
209
|
+
def schema_path_pointer: () -> String
|
|
210
|
+
|
|
211
|
+
# Evaluation path as JSON Pointer string (RFC 6901), pre-computed in Rust.
|
|
212
|
+
def evaluation_path_pointer: () -> String
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Type of validation error with contextual data.
|
|
216
|
+
class ValidationErrorKind
|
|
217
|
+
# Keyword name that caused the error (e.g., "type", "required", "format").
|
|
218
|
+
def name: () -> String
|
|
219
|
+
|
|
220
|
+
# Associated value for the error (varies by error type).
|
|
221
|
+
def value: () -> untyped
|
|
222
|
+
|
|
223
|
+
# Convert to hash representation.
|
|
224
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
225
|
+
|
|
226
|
+
def inspect: () -> String
|
|
227
|
+
def to_s: () -> String
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Structured evaluation output following JSON Schema specification.
|
|
231
|
+
class Evaluation
|
|
232
|
+
# Whether the instance is valid.
|
|
233
|
+
def valid?: () -> bool
|
|
234
|
+
|
|
235
|
+
# Flag output format (simplest).
|
|
236
|
+
# Returns { valid: true/false }
|
|
237
|
+
def flag: () -> Hash[Symbol, untyped]
|
|
238
|
+
|
|
239
|
+
# List output format (flat).
|
|
240
|
+
# Contains { valid: bool, details: [...] }
|
|
241
|
+
def list: () -> Hash[Symbol, untyped]
|
|
242
|
+
|
|
243
|
+
# Hierarchical output format (nested).
|
|
244
|
+
# Contains nested structure following schema hierarchy
|
|
245
|
+
def hierarchical: () -> Hash[Symbol, untyped]
|
|
246
|
+
|
|
247
|
+
# Collected annotations from all evaluated nodes.
|
|
248
|
+
# Each entry contains schemaLocation, instanceLocation, and annotations
|
|
249
|
+
def annotations: () -> Array[Hash[Symbol, untyped]]
|
|
250
|
+
|
|
251
|
+
# Collected errors from all evaluated nodes.
|
|
252
|
+
# Each entry contains schemaLocation, instanceLocation, error, and absoluteKeywordLocation
|
|
253
|
+
def errors: () -> Array[Hash[Symbol, untyped]]
|
|
254
|
+
|
|
255
|
+
def inspect: () -> String
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Schema registry for reference resolution.
|
|
259
|
+
class Registry
|
|
260
|
+
# Create a registry from URI/schema pairs.
|
|
261
|
+
# @param resources Array of [uri, schema] pairs
|
|
262
|
+
# @param draft Optional draft version constant
|
|
263
|
+
# @param retriever Custom schema retriever proc for dynamic resolution
|
|
264
|
+
def initialize: (Array[[String, untyped]] resources, ?draft: draft?, ?retriever: (^(String) -> untyped)?) -> void
|
|
265
|
+
|
|
266
|
+
def inspect: () -> String
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Raised when a reference cannot be resolved.
|
|
270
|
+
class ReferencingError < StandardError
|
|
271
|
+
attr_reader message: String
|
|
272
|
+
def initialize: (String message) -> void
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Meta-schema validation.
|
|
276
|
+
module Meta
|
|
277
|
+
# Validate a schema against its meta-schema.
|
|
278
|
+
def self.valid?: (untyped schema, ?registry: Registry?) -> bool
|
|
279
|
+
|
|
280
|
+
# Validate a schema and raise on error.
|
|
281
|
+
def self.validate!: (untyped schema, ?registry: Registry?) -> nil
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Email format validation options.
|
|
285
|
+
class EmailOptions
|
|
286
|
+
# Create email validation options.
|
|
287
|
+
# @param require_tld Require top-level domain (default: false)
|
|
288
|
+
# @param allow_domain_literal Allow domain literals like [127.0.0.1] (default: true)
|
|
289
|
+
# @param allow_display_text Allow display names like "Name <email>" (default: true)
|
|
290
|
+
# @param minimum_sub_domains Minimum number of subdomains required (default: nil)
|
|
291
|
+
def initialize: (
|
|
292
|
+
?require_tld: bool?,
|
|
293
|
+
?allow_domain_literal: bool?,
|
|
294
|
+
?allow_display_text: bool?,
|
|
295
|
+
?minimum_sub_domains: Integer?
|
|
296
|
+
) -> void
|
|
297
|
+
|
|
298
|
+
# Whether TLD is required.
|
|
299
|
+
def require_tld: () -> bool
|
|
300
|
+
|
|
301
|
+
# Whether domain literals are allowed.
|
|
302
|
+
def allow_domain_literal: () -> bool
|
|
303
|
+
|
|
304
|
+
# Whether display text is allowed.
|
|
305
|
+
def allow_display_text: () -> bool
|
|
306
|
+
|
|
307
|
+
# Minimum number of subdomains.
|
|
308
|
+
def minimum_sub_domains: () -> Integer?
|
|
309
|
+
|
|
310
|
+
def inspect: () -> String
|
|
311
|
+
def to_s: () -> String
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Regex engine options.
|
|
315
|
+
class RegexOptions
|
|
316
|
+
# Create regex engine options.
|
|
317
|
+
# @param size_limit Maximum compiled regex size in bytes
|
|
318
|
+
# @param dfa_size_limit Maximum DFA size in bytes
|
|
319
|
+
def initialize: (?size_limit: Integer?, ?dfa_size_limit: Integer?) -> void
|
|
320
|
+
|
|
321
|
+
# Maximum compiled regex size.
|
|
322
|
+
def size_limit: () -> Integer?
|
|
323
|
+
|
|
324
|
+
# Maximum DFA size.
|
|
325
|
+
def dfa_size_limit: () -> Integer?
|
|
326
|
+
|
|
327
|
+
def inspect: () -> String
|
|
328
|
+
def to_s: () -> String
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Fancy regex engine options (ECMA-262 patterns).
|
|
332
|
+
class FancyRegexOptions
|
|
333
|
+
# Create fancy regex engine options.
|
|
334
|
+
# @param backtrack_limit Maximum backtracking steps
|
|
335
|
+
# @param size_limit Maximum compiled regex size
|
|
336
|
+
# @param dfa_size_limit Maximum DFA size
|
|
337
|
+
def initialize: (
|
|
338
|
+
?backtrack_limit: Integer?,
|
|
339
|
+
?size_limit: Integer?,
|
|
340
|
+
?dfa_size_limit: Integer?
|
|
341
|
+
) -> void
|
|
342
|
+
|
|
343
|
+
# Maximum backtracking steps.
|
|
344
|
+
def backtrack_limit: () -> Integer?
|
|
345
|
+
|
|
346
|
+
# Maximum compiled regex size.
|
|
347
|
+
def size_limit: () -> Integer?
|
|
348
|
+
|
|
349
|
+
# Maximum DFA size.
|
|
350
|
+
def dfa_size_limit: () -> Integer?
|
|
351
|
+
|
|
352
|
+
def inspect: () -> String
|
|
353
|
+
def to_s: () -> String
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# HTTP client options for remote schema retrieval.
|
|
357
|
+
class HttpOptions
|
|
358
|
+
# Create HTTP client options.
|
|
359
|
+
# @param timeout Request timeout in seconds
|
|
360
|
+
# @param connect_timeout Connection timeout in seconds
|
|
361
|
+
# @param tls_verify Verify TLS certificates (default: true)
|
|
362
|
+
# @param ca_cert Path to CA certificate file
|
|
363
|
+
def initialize: (
|
|
364
|
+
?timeout: Float?,
|
|
365
|
+
?connect_timeout: Float?,
|
|
366
|
+
?tls_verify: bool?,
|
|
367
|
+
?ca_cert: String?
|
|
368
|
+
) -> void
|
|
369
|
+
|
|
370
|
+
# Request timeout in seconds.
|
|
371
|
+
def timeout: () -> Float?
|
|
372
|
+
|
|
373
|
+
# Connection timeout in seconds.
|
|
374
|
+
def connect_timeout: () -> Float?
|
|
375
|
+
|
|
376
|
+
# Whether to verify TLS certificates.
|
|
377
|
+
def tls_verify: () -> bool
|
|
378
|
+
|
|
379
|
+
# Path to CA certificate file.
|
|
380
|
+
def ca_cert: () -> String?
|
|
381
|
+
|
|
382
|
+
def inspect: () -> String
|
|
383
|
+
def to_s: () -> String
|
|
384
|
+
end
|
|
385
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jsonschema_rs
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.42.0
|
|
5
|
+
platform: aarch64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- Dmitry Dygalo
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bigdecimal
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.1'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '5'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '3.1'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5'
|
|
33
|
+
description: High-performance JSON Schema validator with support for Draft 4, 6, 7,
|
|
34
|
+
2019-09, and 2020-12.
|
|
35
|
+
email:
|
|
36
|
+
- dmitry@dygalo.dev
|
|
37
|
+
executables: []
|
|
38
|
+
extensions: []
|
|
39
|
+
extra_rdoc_files: []
|
|
40
|
+
files:
|
|
41
|
+
- CHANGELOG.md
|
|
42
|
+
- LICENSE
|
|
43
|
+
- MIGRATION.md
|
|
44
|
+
- README.md
|
|
45
|
+
- ext/jsonschema/extconf.rb
|
|
46
|
+
- lib/jsonschema/3.2/jsonschema_rb.so
|
|
47
|
+
- lib/jsonschema/3.3/jsonschema_rb.so
|
|
48
|
+
- lib/jsonschema/3.4/jsonschema_rb.so
|
|
49
|
+
- lib/jsonschema/4.0/jsonschema_rb.so
|
|
50
|
+
- lib/jsonschema/version.rb
|
|
51
|
+
- lib/jsonschema_rs.rb
|
|
52
|
+
- sig/jsonschema.rbs
|
|
53
|
+
homepage: https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-rb
|
|
54
|
+
licenses:
|
|
55
|
+
- MIT
|
|
56
|
+
metadata:
|
|
57
|
+
homepage_uri: https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-rb
|
|
58
|
+
source_code_uri: https://github.com/Stranger6667/jsonschema
|
|
59
|
+
changelog_uri: https://github.com/Stranger6667/jsonschema/blob/master/crates/jsonschema-rb/CHANGELOG.md
|
|
60
|
+
documentation_uri: https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-rb#readme
|
|
61
|
+
bug_tracker_uri: https://github.com/Stranger6667/jsonschema/issues
|
|
62
|
+
funding_uri: https://github.com/sponsors/Stranger6667
|
|
63
|
+
rubygems_mfa_required: 'true'
|
|
64
|
+
post_install_message:
|
|
65
|
+
rdoc_options: []
|
|
66
|
+
require_paths:
|
|
67
|
+
- lib
|
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '3.2'
|
|
73
|
+
- - "<"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 4.1.dev
|
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: 3.3.11
|
|
81
|
+
requirements: []
|
|
82
|
+
rubygems_version: 3.5.23
|
|
83
|
+
signing_key:
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: A high-performance JSON Schema validator for Ruby
|
|
86
|
+
test_files: []
|