jtd 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem](https://img.shields.io/gem/v/jtd)](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