Package: podm
PODM: (P)ython (O)bject - (D)ictionary (M)apperThis library is intended to create objects that easily serialize to dictionaries that can be later stored as JSON or YAML.
It is intended as a replacement of jsonpickle for cases where jsonpickle output format is not good at all.Features:Support for ordered dictionaries or custom mapping classesCustom field serialization/deserializationValidatorsJson Schema generationInstallationpip3 install podmSome use case samplesVery simple case:frompodmimportJsonObject,PropertyclassPerson(JsonObject):first_name=Property()last_name=Property()person=Person(first_name='John',last_name='Doe')person_dict=person.to_dict()print(json.dumps(person_dict,indent=4))# will output{"py/object":"__main__.Person","first_name":"John","last_name":"Doe"}Notice the field "py/object", if you don't need it, you can specify on the class declaration:classPerson(JsonObject):__add_type_identifier__=Falsefirst_name=Property()last_name=Property()If you need to specify a different name when the field is converted to dictionary:classPerson(JsonObject):__add_type_identifier__=Falsefirst_name=Property('first-name')last_name=Property('last-name')person=Person(first_name='John',last_name='Doe')person_dict=person.to_dict()print(json.dumps(person_dict,indent=4))# will output{"first-name":"John","last-name":"Doe"}Now, when you need to convert the dictionary back to object:person = Person.from_dict({'first-name':'John', 'last-name':'Doe'})In case you don't want to explicitly use the class, or you are working with a hierarchy of classes, you will need the type identifier field in order to let the library recognize the object type:some_dictionary={"py/object":"__main__.Person","first-name":"John","last-name":"Doe"}some_obj=JsonObject.parse(some_dictionary)Handling complex data types:frompodmimportJsonObject,Property,HandlerclassDateTimeHandler(Handler):"""Define a custom handler for datetime objects"""defencode(self,obj):return{'year':obj.year,'month':obj.month,'day':obj.day,'hour':obj.hour,'minute':obj.minute,'second':obj.second,'microsecond':obj.microsecond}defdecode(self,obj_data):returndatetime(**obj_data)classEntity(JsonObject):"""A base class for the object model"""oid=Property()created=Property('created',handler=DateTimeHandler(),default=datetime.now)# Default value when object is instantiatedclassCompany(Entity):company_name=Property('company-name')# Specify a different field name in json.description=Property()classSector(Entity):employees=Property('employees',default=[])classEmployee(Entity):name=Property()company=Company(name='My great company',description='....')json_data=company.to_dict()company_2=Company.from_dict(json_data)Jsonpickle format supportdata={'py/object':'Company','py/state':{'company-name':'master','description':'some description'}}company=JsonObject.parse(data)Automatically generated getters/setters.If they are declared property accessors will use them instead.classCompany(JsonObject):company_name=Property('company-name')# Specify a different field name in json.# Automatically generated gettercompany_name=company.get_company_name()# Also property accessorscompany_name=company.company_name# And private attributescompany_name=company._company_nameWrite custom getters and settersclassCompany(JsonObject):company_name=Property('company-name')# Specify a different field name in json.defget_company_name(self):print('Getter called!!!')# generated attributereturnself._company_name# So, when calling the property getter ...company_name=company.company_name# will print 'Getter called!!!'Enum supportIt is possible to decide how to serialize/deserialize enums.classInvoiceType(Enum):TYPE_A=1TYPE_B=2classInvoice(JsonObject):invoice_type=Property(type=InvoiceType,enum_as_str=True)invoice=Invoice(invoice_type=InvoiceType.TYPE_A)serialized=invoice.to_dict()print(serialized['invice_type'])# Will print 'TYPE_A'classInvoice(JsonObject):invoice_type=Property(type=InvoiceType)invoice=Invoice(invoice_type=InvoiceType.TYPE_A)serializd=invoice.to_dict()print(serialized['invoice_type'])# Will print 1Json Schema generation.Check test cases for examples.Validators.Check test cases for examples.