LoginSignup
7
6

More than 5 years have passed since last update.

[Python] Voluptuousを用いたJSONのvalidation

Last updated at Posted at 2016-01-01

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.

リポジトリ内の説明でも触れているが、すごい名前だ。

voluptuous
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の方法

以下のいずれか

  1. 取り得る値の直接指定。Any、Range、等で幅を持たせることもできる。
  2. クラス(int, float等の他、six.text_typeといった指定も可)
    • クラスが合致していれば値は何でもOK
  3. validation関数を指定する
    • 前述のvalidate_io_size関数がこれ
    • validation関数は条件を満たさない場合はInvalid例外を投げる

動作例

環境

  • Python 2.5/2.7
  • voluptuous 0.8.8

正常動作例

valid1.json
{
    "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'}
#

正常動作例(必須パラメータ省略)

valid2.json
{
    "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'}

必須パラメータ意外は無くてもエラーにならない。

エラー動作例

invalid.json
{
    "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関数指定時)

invalid2.json
{
    "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関数を指定した場合もこのように。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6