Package: dicty
DictObjectSubclassing this type you can declare your object model.DictObjectitself isdictsubclass so you can access object properties as attribute or as an item:classFoo(dicty.DictObject):foo=dicty.Field()obj=Foo(foo='bar')obj.foo# 'bar'obj['foo']# 'bar'Object constructor accepts properties as keyword arguments, or you can create
instance withfromjson()classmethod that takes object dictionary (e.g. resultjson.loads()) as an argument:obj=Foo(foo='bar')obj=Foo.fromjson({'foo':'bar'})You can passDictObjectinstance directly to json library or calljsonize()method first that will return plain dict version of your object with only
declared fields left:obj=Foo.fromjson({'foo':123,'bar':123})obj=={'foo':123,'bar':123}obj.jsonize()=={'foo':123}Name aliasingIf you don’t like naming scheme in JSON objects, API and so on. Dicty allows to
choose whatever python name you like while manually specify dictionary key. For
instance map camel-case keys to their underscore counterparts:classFoo(dicty.DictObject):prop_foo=dicty.Field('propFoo')obj=Foo(prop_foo=123)obj=Foo.fromjson({'propFoo':123})obj.prop_fooobj['propFoo']SubclassingDictObjectsupports subclassing:classFoo(dicty.DictObject):foo=dicty.Field()classBar(Foo):bar=dicty.Field()obj=Bar.fromjson({'foo':1,'bar':2})printobj.jsonize()# {'foo': 1, 'bar': 2}Mixins are supported as well:classFooMixIn(object):foo=dicty.Field()classBar(dicty.DictObject,FooMixIn):bar=dicty.Field()obj=Bar.fromjson({'foo':1,'bar':2})printobj.jsonize()# {'foo': 1, 'bar': 2}Fieldsdicty.Fieldis baseclass for all dicty fields. You can use itself directly to
declare a field with no special type info.Optional fields and default valuesAccessing field that is not set will lead toAttributeError:
You can specify default value for your field:classFoo(dicty.DictObject):foo=dicty.Field()obj=Foo()obj.foo# raises AttributeErrorYou can mark field as optional, in this caseNonewill be returned if it was
not set before:classFoo(dicty.DictObject):foo=dicty.Field(optional=True)obj=Foo()obj.foo# NoneFor optional fields you can specify default value other thanNonewithdefaultargument:classFoo(dicty.DictObject):foo=dicty.Field(optional=True,default=123)obj=Foo()obj.foo# 123obj=={}Please note that default value does not affect internal dictionary. But if
default value is NOT hashable dict key will be set ongetattraccess.There is also an option to suplydefault_funcit’s get default value for
object’s field. It takes object instance as an argument. Value returned bydefault_funcis always stored in dict:classFoo(dicty.DictObject):id=dicty.Field(optional=True,default_func=lambdaobj:uuid.uuid4().hex)obj=Foo()obj=={}obj.id# Would be populated with newly generated UUIDobj=={'id':'07d0af8affaf46c885cc251e17dbc37a'}Available FieldsDicty is shipped with the follwing:BooleanFieldDateFieldDatetimeFieldDictFieldFloatFieldIntegerFieldListFieldNativeDateFieldNativeDatetimeFieldNumberFieldRegexpStringFieldStringFieldTypedDictFieldTypedListFieldTypedObjectFieldSample usageWith dicty you can easily describe your data model and then use it to encode/decode JSON objects. It supports
data validataion, optional parameters, default values, nested objects and so on.importdictyclassMyDoc(dicty.DictObject):prop1=dicty.StringField()prop2=dicty.IntegerField()# Regular constructordoc=MyDoc(prop1='foo',prop2=123)printdoc.prop1# you can access values as attributesprintdoc['prop2']# as well as dictionary itemsprintjson.dumps(doc)printjson.dumps(doc.jsonify())# Jsonify will clean and validate output data# Create instance from dictionarydoc=MyDoc.fromjson({'prop1':'foo','prop2':123})# would raise dicty.FieldError heredoc=MyDoc.fromjson({'prop1':123,'prop2':123})Nested ObjectsimportdictyclassFoo(dicty.DictObject):classBar(dicty.DictObject):prop=dicty.StringField()bar=dicty.TypedObjectField(Bar)obj=Foo()obj.bar.prop=123printobj# {'bar': {'prop': 123}}Mongo-style key pathesDicty allows to build key pathes that can be used to create mongo query:classFoo(dicty.DictObject):bar=dicty.Field('myBar')printFoo.bar# 'myBar' full path to the itemprintFoo.bar.key# 'myBar' only leaf keyprintFoo.bar.attname# 'bar' python attribute nameNested object:classBar(dicty.DictObject):foo=dicty.TypedObjectField(Foo)printBar.foo# 'foo'printBar.foo.bar# 'foo.myBar'List of objects:classBar(dicty.DictObject):items=dicty.TypedListField(Foo)printBar.items.foo# 'items.myBar' without indexprintBar.items[0].foo# 'items.0.myBar' indexed pathDict of objects:classBar(dicty.DictObject):items=dicty.TypedDictField(Foo)# With indexprintBar.items['maurice'].bar# 'items.maurice.myBar'# Would raise IndexErrorprintBar.items['x.y'].bar