3
3

More than 5 years have passed since last update.

Python DictShieldを使用してJSONオブジェクトのバリデーションを行う

Last updated at Posted at 2013-12-28

書いた時はさっぱり気付いていませんでしたが、現在はschematicsに移行しているそうです。そのうちschematics版も書く…かも。


dictshieldはJSONオブジェクトをバリデーションするためのライブラリ。

クラスで定義出来るので、普段使っているdjangoのモデルやフォームクラス、mongoengineのドキュメントクラスなどと似ていること、コードベースがコンパクトで見通しが良いことから、使いやすそうだったのでお試し。コードの中を追っていくと、MongoDBやJSON Schemaも考慮されているみたい。

使い方

基本編

documents.py
from dictshield.document import Document
from dictshield.fields import StringField, IntField, FloatField, BooleanField, DateTimeField

class SampleDocument(Document):
    id = IntField(min_value=0)
    name = StringField()
    gps_attached = BooleanField()
    temperature = FloatField()
    created_at = DateTimeField()

JSONオブジェクトの検査は、JSONオブジェクトをdictに変換してからドキュメントクラスに放り込む。

import json

json_data = '{"id": 1, "name": "foo", "gps_attached": true, "temperature": 23.5, "created_at": "2013-01-01T12:34:56" }'

data = json.loads(json_data)

document = SampleDocument(**data)
document.validate()  # Trueが返ってくる

ネストした(?)JSONオブジェクトのハンドリング

ネストした(?)JSONオブジェクトを使用するにはEmbeddedDocumentクラスを使用する。周辺センサの情報を分離してみる例。

documents.py
from dictshield.document import Document, EmbeddedDocument
from dictshield.fields import StringField, IntField, FloatField, BooleanField, DateTimeField
from dictshield.fields.compound import EmbeddedDocumentField


class PeripheralEmbeddedDocument(EmbeddedDocument):
    gps_attached = BooleanField()
    temperature = FloatField()

class SampleDocument(Document):
    id = IntField()
    name = StringField(max_length=5)
    created_at = DateTimeField()
    peripheral = EmbeddedDocumentField(PeripheralEmbeddedDocument)
data = {
    u'created_at': u'2013-01-01T12:34:56',
    u'id': 1,
    u'name': u'foo',
    u'peripheral': {
        u'gps_attached': True,
        u'temperature': 23.5
    }
}

document = SampleDocument(**data)
document.validate()  # Trueが返ってくる

例外

バリデーションに失敗するとShieldExceptionが飛んでくる。

data = {
    u'created_at': u'2013-01-01T12:34:56',
    u'id': 1,
    u'name': u'hogheoge',  # 長い
    u'peripheral': {
        u'gps_attached': True,
        u'temperature': 23.5
    }
}

document = SampleDocument(**data)
document.validate()
---------------------------------------------------------------------------
ShieldException                           Traceback (most recent call last)
<ipython-input-76-8d15894a526a> in <module>()
----> 1 document.validate()

/somewhere/lib/python2.7/site-packages/dictshield/document.pyc in validate(self, validate_all)
    333                 # NB: raising a ShieldDocException in this case would be more
    334                 # consistent, but existing code might expect ShieldException
--> 335                 raise err
    336
    337         if errs:

ShieldException: String value is too long - name:hogheoge

気付いたこと

  • IntFieldmax_value, min_valueオプションが動いていないような…。

参考

3
3
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
3
3