PythonでVoluptuousライブラリを使ってJSONの値の検証(validation)を実施する方法。
Voluptuousとは
PythonのJSON等のvalidationライブラリ。
公式リポジトリ: https://github.com/alecthomas/voluptuous
Voluptuous, despite the name, is a Python data validation library. It is primarily intended for validating data coming into Python as JSON, YAML, etc.
リポジトリ内の説明でも触れているが、すごい名前だ。
1 肉欲にふける,酒色におぼれる,官能的な.
2 肉感的な,色っぽい,あだっぽい,セクシーな.
3〈感触など〉心地よい.
install
Python 2.6以上
pipでインストールできる。
# pip install voluptuous
Python 2.5
公式では非サポートなものの Python2.5でVoluptuousをインストールする でインストールと本記事レベルの動作は可。
Sample program
動作を示すサンプルプログラム。
get_schema 内のSchema宣言が核となるところ。
これがVoluptuousでのJSONスキーマの定義となる。
from __future__ import with_statement
import re
import sys
import json # Python 2.5ではsimplejson
import six
from voluptuous import Schema, Required, Any, Range, Invalid, ALLOW_EXTRA
def validate_io_size(v):
if re.search("^[0-9]+[bkm]", v) is None:
raise Invalid("not a valid value (%s)" % str(v))
def get_schema():
schema = Schema({
"comment" : six.text_type,
Required("operation") : Any("read", "write"),
"thread" : Range(min=1),
Required("io_size") : validate_io_size,
Required("access_percentage") : Range(min=1, max=100),
}, extra=ALLOW_EXTRA)
return schema
def main():
schema = get_schema()
with open(sys.argv[1], "r") as fp:
dict_sample = json.load(fp)
schema(dict_sample)
six.print_(dict_sample)
return 0
if __name__ == '__main__':
sys.exit(main())
詳細
Voluptuous用語
キーワード | 意味 |
---|---|
Required | 必須パラメータ。これをつけていないパラメータは省いてもエラーにならない。 |
Any | 宣言中のいずれかの値ならOK。 |
Range | min以上、max以下ならOK。min or maxのみ指定することもできる。 |
ALLOW_EXTRA | スキーマに定義が無いパラメータの存在を許す。 |
validationの方法
以下のいずれか
- 取り得る値の直接指定。Any、Range、等で幅を持たせることもできる。
- クラス(int, float等の他、six.text_typeといった指定も可)
- クラスが合致していれば値は何でもOK
- validation関数を指定する
- 前述のvalidate_io_size関数がこれ
- validation関数は条件を満たさない場合はInvalid例外を投げる
動作例
環境
- Python 2.5/2.7
- voluptuous 0.8.8
正常動作例
{
"comment" : "comment",
"operation" : "write",
"thread" : 8,
"io_size" : "8k",
"access_percentage" : 100
}
# python voluptuous_sample.py valid1.json
{u'comment': u'comment', u'operation': u'write', u'access_percentage': 100, u'thread': 8, u'io_size': u'8k'}
#
正常動作例(必須パラメータ省略)
{
"operation" : "write",
"io_size" : "8k",
"access_percentage" : 100
}
# python voluptuous_sample.py valid2.json
{u'operation': u'write', u'access_percentage': 100, u'io_size': u'8k'}
必須パラメータ意外は無くてもエラーにならない。
エラー動作例
{
"comment" : "comment",
"operation" : "<invalid value>",
"thread" : 8,
"io_size" : "8k",
"access_percentage" : 100
}
# python voluptuous_sample.py invalid.json
Traceback (most recent call last):
File "voluptuous_sample.py", line 36, in <module>
sys.exit(main())
File "voluptuous_sample.py", line 29, in main
schema(dict_sample)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 337, in __call__
return self._compiled([], data)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 635, in validate_dict
return base_validate(path, iteritems(data), out)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 471, in validate_mapping
raise MultipleInvalid(errors)
voluptuous.MultipleInvalid: not a valid value for dictionary value @ data[u'operation']
#
スキーマに合致しないパラメータがあるとvoluptuous.MultipleInvalidが送出され、
パラメータ(例ではoperation)の値が正しくないよ、というメッセージが出る。
エラー動作例(validation関数指定時)
{
"comment" : "comment",
"operation" : "write",
"thread" : 8,
"io_size" : "a8k",
"access_percentage" : 100
}
# python voluptuous_sample.py invalid2.json
Traceback (most recent call last):
File "voluptuous_sample.py", line 38, in <module>
sys.exit(main())
File "voluptuous_sample.py", line 31, in main
schema(dict_sample)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 337, in __call__
return self._compiled([], data)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 635, in validate_dict
return base_validate(path, iteritems(data), out)
File "/usr/local/lib/python2.7/dist-packages/voluptuous.py", line 471, in validate_mapping
raise MultipleInvalid(errors)
voluptuous.MultipleInvalid: not a valid value (a8k) for dictionary value @ data[u'io_size']
validation関数を指定した場合もこのように。