Python のバリデータだと、以前このブログでも
FormEncode を扱ったことがある。
今回は同様のパッケージとして jsonschema について書いてみる。
まず、元々の “jsonschema” というものは JSON の構造を JSON で記述するための仕様を指している。
そして、今回紹介する Python パッケージの jsonschema は、その仕様を元にバリデータを実装したものだ。
元々の “jsonschema” の仕様については以下の Web サイトを参照してもらいたい。
http://json-schema.org/
まずインストールは PyPI から。
$ pip install jsonschema
jsonschema のバリデーション・ルールは辞書と文字列で記述する。
詳しくは json-schema.org の仕様を確認すると良いが、以下のサンプルに目を通すだけでも雰囲気は掴めるはず。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import jsonschema
SCHEMA = {
'type': 'object',
'properties': {
'name': {
'type': 'string',
'minLength': 1,
'maxLength': 64,
},
'age': {
'age': 'integer',
'minimum': 0,
'maximum': 100,
},
},
'required': [
'name',
'age',
],
}
if __name__ == '__main__':
import json
ok = '''
{
"name": "Foo",
"age": 15
}
'''
ok_dict = json.loads(ok)
jsonschema.validate(ok_dict, SCHEMA)
ng = '''
{
"name": "Bar"
}
'''
ng_dict = json.loads(ng)
jsonschema.validate(ng_dict, SCHEMA)
もし jsonschema.validate() にルールから外れた辞書が入ると ValidationError が上がる。
例えば上記では、定義で ‘age’ が required (必須) になっているにも関わらず、変数 ng に代入した文字列は ‘age’ が無い。
Traceback (most recent call last):
File "/Users/amedama/Documents/workspace/js1.py", line 44, in <module>
jsonschema.validate(ng_dict, SCHEMA)
File "/Users/amedama/.virtualenvs/py34/lib/python3.4/site-packages/jsonschema/validators.py", line 432, in validate
cls(schema, *args, **kwargs).validate(instance)
File "/Users/amedama/.virtualenvs/py34/lib/python3.4/site-packages/jsonschema/validators.py", line 117, in validate
raise error
jsonschema.exceptions.ValidationError: 'age' is a required property
Failed validating 'required' in schema:
{'properties': {'age': {'age': 'integer',
'maximum': 100,
'minimum': 0},
'name': {'maxLength': 64,
'minLength': 1,
'type': 'string'}},
'required': ['name', 'age'],
'type': 'object'}
On instance:
{'name': 'Bar'}
もちろん、オブジェクトが複雑にネストした構造になっていてもバリデートできる。
例えば、以下では ‘emails’ にたどり着くまでに構造が ‘array’ -> ‘object’ -> ‘array’ -> ‘string’ と入れ子になっている。
尚、’array’ (配列) を扱う場合には ‘properties’ ではなく ‘items’ で中身を表す。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import jsonschema
SCHEMA = {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'name': {
'type': 'string'
},
'emails': {
'type': 'array',
'items': {
'type': 'string',
},
},
},
'required': [
'name',
'emails',
],
},
}
if __name__ == '__main__':
import json
ok = '''
[
{
"name": "Foo",
"emails": [
"foo@example.jp"
]
},
{
"name": "Bar",
"emails": [
"bar@example.com"
]
}
]
'''
ok_dict = json.loads(ok)
jsonschema.validate(ok_dict, SCHEMA)
FormEncode もそうだけど、一般的なバリデータは独自のクラスを組み合わせてルールを記述していくものが多い。
それに対し jsonschema はルールの記述が Python の辞書と文字列だけで行える点が魅力だ。
また、jsonschema を使ったバリデータは各言語に実装があるので、考え方やルールが使いまわせるのもありがたい。