Fast JSON schema for Python¶
About¶
fastjsonschema
implements validation of JSON documents by JSON schema.
The library implements JSON schema drafts 04, 06, and 07. The main purpose is
to have a really fast implementation. See some numbers:
- Probably the most popular,
jsonschema
, can take up to 5 seconds for valid inputs and 1.2 seconds for invalid inputs.- Second most popular,
json-spec
, is even worse with up to 7.2 and 1.7 seconds.- Last
validictory
, now deprecated, is much better with 370 or 23 milliseconds, but it does not follow all standards, and it can be still slow for some purposes.
With this library you can gain big improvements as fastjsonschema
takes
only about 25 milliseconds for valid inputs and 2 milliseconds for invalid ones.
Pretty amazing, right? :-)
Technically it works by generating the most stupid code on the fly, which is fast but is hard to write by hand. The best efficiency is achieved when a validator is compiled once and used many times, of course. It works similarly like regular expressions. But you can also generate the code to a file, which is even slightly faster.
You can run the performance benchmarks on your computer or server with the included script:
$ make performance
fast_compiled valid ==> 0.0464646
fast_compiled invalid ==> 0.0030227
fast_file valid ==> 0.0461219
fast_file invalid ==> 0.0030608
fast_not_compiled valid ==> 11.4627202
fast_not_compiled invalid ==> 2.5726230
jsonschema valid ==> 7.5844927
jsonschema invalid ==> 1.9204665
jsonschema_compiled valid ==> 0.6938364
jsonschema_compiled invalid ==> 0.0359244
jsonspec valid ==> 9.0715843
jsonspec invalid ==> 2.1650488
validictory valid ==> 0.4874793
validictory invalid ==> 0.0232244
This library follows and implements JSON schema draft-04, draft-06, and draft-07. Sometimes it’s not perfectly clear, so I recommend also check out this understanding JSON schema.
Note that there are some differences compared to JSON schema standard:
- Regular expressions are full Python ones, not only what JSON schema allows. It’s easier to allow everything, and also it’s faster to compile without limits. So keep in mind that when you will use a more advanced regular expression, it may not work with other libraries or in other languages.
- Because Python matches new line for a dollar in regular expressions (
a$
matchesa
anda\\n
), instead of$
is used\Z
and all dollars in your regular expression are changed to\\Z
as well. When you want to use dollar as regular character, you have to escape it (\$
).- JSON schema says you can use keyword
default
for providing default values. This implementation uses that and always returns transformed input data.
Usage¶
import fastjsonschema
point_schema = {
"type": "object",
"properties": {
"x": {
"type": "number",
},
"y": {
"type": "number",
},
},
"required": ["x", "y"],
"additionalProperties": False,
}
point_validator = fastjsonschema.compile(point_schema)
try:
point_validator({"x": 1.0, "y": 2.0})
except fastjsonschema.JsonSchemaException as e:
print(f"Data failed validation: {e}")
API¶
-
exception
fastjsonschema.
JsonSchemaValueException
(message, value=None, name=None, definition=None, rule=None)[source]¶ Exception raised by validation function. Available properties:
message
containing human-readable information what is wrong (e.g.data.property[index] must be smaller than or equal to 42
),- invalid
value
(e.g.60
), name
of a path in the data structure (e.g.data.property[index]
),path
as an array in the data structure (e.g.['data', 'property', 'index']
),- the whole
definition
which thevalue
has to fulfil (e.g.{'type': 'number', 'maximum': 42}
), rule
which thevalue
is breaking (e.g.maximum
)- and
rule_definition
(e.g.42
).
Changed in version 2.14.0: Added all extra properties.
-
exception
fastjsonschema.
JsonSchemaDefinitionException
[source]¶ Exception raised by generator of validation function.
-
fastjsonschema.
validate
(definition, data, handlers={}, formats={}, use_default=True, use_formats=True)[source]¶ Validation function for lazy programmers or for use cases when you need to call validation only once, so you do not have to compile it first. Use it only when you do not care about performance (even though it will be still faster than alternative implementations).
import fastjsonschema fastjsonschema.validate({'type': 'string'}, 'hello') # same as: compile({'type': 'string'})('hello')
Preferred is to use
compile
function.
-
fastjsonschema.
compile
(definition, handlers={}, formats={}, use_default=True, use_formats=True)[source]¶ Generates validation function for validating JSON schema passed in
definition
. Example:import fastjsonschema validate = fastjsonschema.compile({'type': 'string'}) validate('hello')
This implementation supports keyword
default
(can be turned off by passing use_default=False):validate = fastjsonschema.compile({ 'type': 'object', 'properties': { 'a': {'type': 'number', 'default': 42}, }, }) data = validate({}) assert data == {'a': 42}
Supported implementations are draft-04, draft-06 and draft-07. Which version should be used is determined by $draft in your
definition
. When not specified, the latest implementation is used (draft-07).validate = fastjsonschema.compile({ '$schema': 'http://json-schema.org/draft-04/schema', 'type': 'number', })
You can pass mapping from URI to function that should be used to retrieve remote schemes used in your
definition
in parameterhandlers
.Also, you can pass mapping for custom formats. Key is the name of your formatter and value can be regular expression, which will be compiled or callback returning bool (or you can raise your own exception).
validate = fastjsonschema.compile(definition, formats={ 'foo': r'foo|bar', 'bar': lambda value: value in ('foo', 'bar'), })
Note that formats are automatically used as assertions. It can be turned off by passing use_formats=False. When disabled, custom formats are disabled as well. (Added in 2.19.0.)
Exception
JsonSchemaDefinitionException
is raised when generating the code fails (bad definition).Exception
JsonSchemaValueException
is raised from generated function when validation fails (data do not follow the definition).
-
fastjsonschema.
compile_to_code
(definition, handlers={}, formats={}, use_default=True, use_formats=True)[source]¶ Generates validation code for validating JSON schema passed in
definition
. Example:import fastjsonschema code = fastjsonschema.compile_to_code({'type': 'string'}) with open('your_file.py', 'w') as f: f.write(code)
You can also use it as a script:
echo "{'type': 'string'}" | python3 -m fastjsonschema > your_file.py python3 -m fastjsonschema "{'type': 'string'}" > your_file.py
Exception
JsonSchemaDefinitionException
is raised when generating the code fails (bad definition).