json­s­che­ma is a gre­at lib­ra­ry for vali­da­ting JSON data with JSON sche­ma in Python. It also allows you to spe­ci­fy cus­tom JSON sche­ma types, for­mats and even vali­da­tors. Unfor­tu­na­te­ly, the docu­men­tati­on is not very clear about the way how to cre­a­te cus­to­mi­zed vali­da­tors.

This gui­de will show you an exam­ple how to cre­a­te a cus­tom vali­da­tor, that will add:

  • Type flo­at – json­s­che­ma knows by default only type num­ber, which covers all num­bers (inte­gers, flo­a­ting point num­bers, com­plex num­bers, …).
  • For­mat even – limi­ting any num­ber to even num­bers only.
  • Vali­da­tor is_positive – accep­ting only posi­ti­ve num­bers when set to True and all the rest if set to Fal­se.

Custom jsonschema validator class

To add sup­port for cus­tom type, for­mat, and vali­da­tor, we must cre­a­te a new IVa­li­da­tor class. We will base it on Draft4Validator. Then we will cre­a­te a functi­on that will work as vali­da­tor for posi­ti­ve num­bers, cre­a­te ano­ther functi­on as a for­mat chec­ker for even num­bers and last­ly, add flo­at as a new type.

We will wri­te the exam­ple as a unit test Test­Ca­se, so we can easi­ly test at the end that our new vali­da­tor works as expec­ted.

Schema definition

Let us first add requi­red imports and defi­ne the sche­ma that we will use for chec­king our JSON data:

This sche­ma will accept JSON in for­mat {‘value’: num­ber}, whe­re num­ber is even, posi­ti­ve and flo­at (2.0, 4.0, etc.).

Custom JSON schema validator

Next, we will defi­ne a vali­da­tor, that will vali­da­te a (non-)positive num­ber based on its settings. The vali­da­tor can be set to a Boo­le­an value. Vali­da­tor must be a functi­on, that accepts exact­ly 4 argu­ments in this order:

  • vali­da­tor – instan­ce of vali­da­tor that is cal­ling this method.
  • value – value set to the vali­da­tor in the sche­ma (in our case True/Fal­se).
  • instan­ce – value that is being vali­da­ted (in our case the num­ber).
  • sche­ma – the part of sche­ma whe­re this vali­da­tor is used (in our case the properties/value dict).
A vali­da­tor must yield a Vali­dati­o­nError when the vali­dati­on fails. You can get inspi­red in jsonschema._validators. Let us add the new vali­da­tor among exis­ting ones and cre­a­te a new IVa­li­da­tor class using this vali­da­tor:

Custom JSON schema format checker

Cre­a­ting a cus­tom for­mat chec­ker aga­in requi­res defi­ning a functi­on, that will check the for­mat. This method can be the regis­te­red either glo­bally for all For­matChec­ker instan­ces or tied to a sin­gle instan­ce. Let us defi­ne a for­mat chec­ker to check that a num­ber is even. First, we need a For­matChec­ker instan­ce. Then we will use this instan­ce as a deco­ra­tor for the for­mat chec­king functi­on. The functi­on must accept exact­ly one argu­ment – the value to check.

A for­mat chec­ker method can also rai­se excep­ti­ons to noti­fy for­mat check fai­lu­re. To do this, pro­vi­de the deco­ra­tor with expec­ted Excep­ti­on class or a tuple of expec­ted clas­ses. The down­si­de of this appro­ach is that the method has to alwa­ys return some value, otherwi­se no excep­ti­on will be still tre­a­ted as a fai­lu­re.

You can also regis­ter the for­mat glo­bally for all For­matChec­ker instan­ces.

Custom type in JSON schema

Now we will put all the pre­vi­ous exam­ple toge­ther to cre­a­te an IVa­li­da­tor instan­ce, that will have a cus­tom vali­da­tor is_positive and cus­tom num­ber for­mat even. We will also add type flo­at.

Checking the result

To check that our new vali­da­tor instan­ce really accepts only posi­ti­ve, even flo­at, let us add some unit test asser­ti­ons.

Complete example


5 Comments

Neil · 2017-05-25 at 14:11

Aweso­me, exact­ly what I was loo­king for! Pity the­re are no exam­ples like these on the python-json­s­che­ma web­si­te.

VITI · 2018-02-28 at 16:56

This is what we need! Thanks a lot.

Tim · 2018-12-29 at 21:16

This is exact­ly what I nee­ded. Thank you!

Tim Bouffard · 2018-12-30 at 15:23

This was very hel­p­ful. The com­ple­te exam­ple works gre­at in ver­si­on 2.6.0 of json­s­che­ma. When try­ing the com­ple­te exam­ple on the newer, ear­ly rele­a­ses 3.0.0.a1,2 and 3 the exam­ple fails. The error is jsonschema.exceptions.UndefinedTypeCheck: Type ‘object’ is unk­nown to this type chec­ker

Even a pared down modi­fied ver­si­on of your exam­ple code has an issue. Not sure what I’m doing wrong.
#!/usr/bin/env python
# -*- coding: utf‑8 -*-

import json­s­che­ma
from json­s­che­ma import vali­da­te, Draft4Validator
from jsonschema.exceptions import Vali­dati­o­nError

def main():
# Defi­ne JSON sche­ma
sche­ma = {
‘type’: ‘object’,
‘pro­per­ties’: {
‘value’: {
‘type’: ‘num­ber’
},
}
}

all_validators = dict(Draft4Validator.VALIDATORS)

MyVa­li­da­tor = jsonschema.validators.create(
meta_schema=Draft4Validator.META_SCHEMA,
validators=all_validators
)

print(‘my vali­da­tor’)
# This works in the new ver­si­on
try:
print(validate({‘value’: ‘a’}, sche­ma))
except Vali­dati­o­nError:
print(‘validation error when cal­ling vali­da­te’)

# this does not work
my_validator = MyValidator(schema)
print(my_validator.is_valid({‘value’: ‘a’}))

if __name__ == ‘__main__’:
main()

Tim Bouffard · 2019-01-07 at 02:00

https://github.com/Julian/jsonschema/issues/509

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.