書いた時はさっぱり気付いていませんでしたが、現在は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
気付いたこと
-
IntField
のmax_value
,min_value
オプションが動いていないような…。
参考
- dictshield
- Schematics こっちに移行してるみたい…