jtd 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +184 -1
- data/lib/jtd/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8db19fa99563fc87cf94665d369a2ab000da1ea9b629c468476f40388587c66
|
4
|
+
data.tar.gz: 59f1124d84474309f31e17caf56a8f6cec5226a2bb842896a3777c471d67642a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14198dced04d5adb6ea790e436291214e9541e4a8641cc86029073401ea8047f0b4487b18821f5e13e347051d9c479d6ae0ca73c40bf62d58c9250cdc928d6df
|
7
|
+
data.tar.gz: 6cb2e3273377f2fa4031db499c2679917fce041eab536913487661d3ab681f053dd84a9f561a11783890852a4c8a7e2b58b0761d7bb9d3aab7c5b21c5a01f290
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1 +1,184 @@
|
|
1
|
-
# jtd: JSON Validation for
|
1
|
+
# jtd: JSON Validation for Python
|
2
|
+
|
3
|
+
[](https://rubygems.org/gems/jtd)
|
4
|
+
|
5
|
+
`jtd` is a Ruby implementation of [JSON Type Definition][jtd], a schema language
|
6
|
+
for JSON. `jtd` primarily gives you two things:
|
7
|
+
|
8
|
+
1. Validating input data against JSON Typedef schemas.
|
9
|
+
2. A Ruby representation of JSON Typedef schemas.
|
10
|
+
|
11
|
+
With this package, you can add JSON Typedef-powered validation to your
|
12
|
+
application, or you can build your own tooling on top of JSON Type Definition.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
You can install this package with `gem`:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
gem install jtd
|
20
|
+
```
|
21
|
+
|
22
|
+
## Documentation
|
23
|
+
|
24
|
+
Detailed API documentation is available online at:
|
25
|
+
|
26
|
+
https://rubydoc.info/gems/jtd/JTD
|
27
|
+
|
28
|
+
For more high-level documentation about JSON Typedef in general, or JSON Typedef
|
29
|
+
in combination with Python in particular, see:
|
30
|
+
|
31
|
+
* [The JSON Typedef Website][jtd]
|
32
|
+
* ["Validating JSON in Ruby with JSON Typedef"][jtd-ruby-validation]
|
33
|
+
|
34
|
+
## Basic Usage
|
35
|
+
|
36
|
+
> For a more detailed tutorial and guidance on how to integrate `jtd` in your
|
37
|
+
> application, see ["Validating JSON in Ruby with JSON
|
38
|
+
> Typedef"][jtd-ruby-validation] in the JSON Typedef docs.
|
39
|
+
|
40
|
+
Here's an example of how you can use this package to validate JSON data against
|
41
|
+
a JSON Typedef schema:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'jtd'
|
45
|
+
|
46
|
+
schema = JTD::Schema.from_hash({
|
47
|
+
'properties' => {
|
48
|
+
'name' => { 'type' => 'string' },
|
49
|
+
'age' => { 'type' => 'uint32' },
|
50
|
+
'phones' => {
|
51
|
+
'elements' => {
|
52
|
+
'type' => 'string'
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
})
|
57
|
+
|
58
|
+
# JTD::validate returns an array of validation errors. If there were no problems
|
59
|
+
# with the input, it returns an empty array.
|
60
|
+
|
61
|
+
# Outputs: []
|
62
|
+
p JTD::validate(schema, {
|
63
|
+
'name' => 'John Doe',
|
64
|
+
'age' => 43,
|
65
|
+
'phones' => ['+44 1234567', '+44 2345678'],
|
66
|
+
})
|
67
|
+
|
68
|
+
# This next input has three problems with it:
|
69
|
+
#
|
70
|
+
# 1. It's missing "name", which is a required property.
|
71
|
+
# 2. "age" is a string, but it should be an integer.
|
72
|
+
# 3. "phones[1]" is a number, but it should be a string.
|
73
|
+
#
|
74
|
+
# Each of those errors corresponds to one of the errors returned by validate.
|
75
|
+
|
76
|
+
# Outputs:
|
77
|
+
#
|
78
|
+
# [
|
79
|
+
# #<struct JTD::ValidationError
|
80
|
+
# instance_path=[],
|
81
|
+
# schema_path=["properties", "name"]
|
82
|
+
# >,
|
83
|
+
# #<struct JTD::ValidationError
|
84
|
+
# instance_path=["age"],
|
85
|
+
# schema_path=["properties", "age", "type"]
|
86
|
+
# >,
|
87
|
+
# #<struct JTD::ValidationError
|
88
|
+
# instance_path=["phones", "1"],
|
89
|
+
# schema_path=["properties", "phones", "elements", "type"]
|
90
|
+
# >
|
91
|
+
# ]
|
92
|
+
p JTD::validate(schema, {
|
93
|
+
'age' => '43',
|
94
|
+
'phones' => ['+44 1234567', 442345678],
|
95
|
+
})
|
96
|
+
```
|
97
|
+
|
98
|
+
## Advanced Usage: Limiting Errors Returned
|
99
|
+
|
100
|
+
By default, `JTD::validate` returns every error it finds. If you just care about
|
101
|
+
whether there are any errors at all, or if you can't show more than some number
|
102
|
+
of errors, then you can get better performance out of `JTD::validate` using the
|
103
|
+
`max_errors` option.
|
104
|
+
|
105
|
+
For example, taking the same example from before, but limiting it to 1 error, we
|
106
|
+
get:
|
107
|
+
|
108
|
+
```python
|
109
|
+
# Outputs:
|
110
|
+
#
|
111
|
+
# [#<struct JTD::ValidationError instance_path=[], schema_path=["properties", "name"]>]
|
112
|
+
options = JTD::ValidationOptions.new(max_errors: 1)
|
113
|
+
p JTD::validate(schema, {
|
114
|
+
'age' => '43',
|
115
|
+
'phones' => ['+44 1234567', 442345678],
|
116
|
+
}, options)
|
117
|
+
```
|
118
|
+
|
119
|
+
## Advanced Usage: Handling Untrusted Schemas
|
120
|
+
|
121
|
+
If you want to run `jtd` against a schema that you don't trust, then you should:
|
122
|
+
|
123
|
+
1. Ensure the schema is well-formed, using the `#verify` method on
|
124
|
+
`JTD::Schema`. That will check things like making sure all `ref`s have
|
125
|
+
corresponding definitions.
|
126
|
+
|
127
|
+
2. Call `JTD::validate` with the `max_depth` option. JSON Typedef lets you write
|
128
|
+
recursive schemas -- if you're evaluating against untrusted schemas, you
|
129
|
+
might go into an infinite loop when evaluating against a malicious input,
|
130
|
+
such as this one:
|
131
|
+
|
132
|
+
```json
|
133
|
+
{
|
134
|
+
"ref": "loop",
|
135
|
+
"definitions": {
|
136
|
+
"loop": {
|
137
|
+
"ref": "loop"
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
```
|
142
|
+
|
143
|
+
The `max_depth` option tells `JTD::validate` how many `ref`s to follow
|
144
|
+
recursively before giving up and raising `JTD::MaxDepthExceededError`.
|
145
|
+
|
146
|
+
Here's an example of how you can use `jtd` to evaluate data against an untrusted
|
147
|
+
schema:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
require 'jtd'
|
151
|
+
|
152
|
+
# validate_untrusted returns true if `data` satisfies `schema`, and false if it
|
153
|
+
# does not. Throws an error if `schema` is invalid, or if validation goes in an
|
154
|
+
# infinite loop.
|
155
|
+
def validate_untrusted(schema, data)
|
156
|
+
schema.verify()
|
157
|
+
|
158
|
+
# You should tune max_depth to be high enough that most legitimate schemas
|
159
|
+
# evaluate without errors, but low enough that an attacker cannot cause a
|
160
|
+
# denial of service attack.
|
161
|
+
options = JTD::ValidationOptions.new(max_depth: 32)
|
162
|
+
JTD::validate(schema, data, options).empty?
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns true
|
166
|
+
validate_untrusted(JTD::Schema.from_hash({ 'type' => 'string' }), 'foo')
|
167
|
+
|
168
|
+
# Returns false
|
169
|
+
validate_untrusted(JTD::Schema.from_hash({ 'type' => 'string' }), nil)
|
170
|
+
|
171
|
+
# Raises ArgumentError (invalid type: nonsense)
|
172
|
+
validate_untrusted(JTD::Schema.from_hash({ 'type' => 'nonsense' }), 'foo')
|
173
|
+
|
174
|
+
# Raises JTD::MaxDepthExceededError (max depth exceeded during JTD::validate)
|
175
|
+
validate_untrusted(JTD::Schema.from_hash({
|
176
|
+
'definitions' => {
|
177
|
+
'loop' => { 'ref' => 'loop' },
|
178
|
+
},
|
179
|
+
'ref' => 'loop',
|
180
|
+
}), nil)
|
181
|
+
```
|
182
|
+
|
183
|
+
[jtd]: https://jsontypedef.com
|
184
|
+
[jtd-ruby-validation]: https://jsontypedef.com/docs/ruby/validation
|
data/lib/jtd/version.rb
CHANGED