PODM: (P)ython (O)bject - (D)ictionary (M)apper
This 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 classes
- Custom field serialization/deserialization
- Validators
- Json Schema generation
Installation
pip3 install podm
Some use case samples
Very simple case:
from podm import JsonObject, Property
class Person(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:
class Person(JsonObject):
__add_type_identifier__ = False
first_name = Property()
last_name = Property()
If you need to specify a different name when the field is converted to dictionary:
class Person(JsonObject):
__add_type_identifier__ = False
first_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:
from podm import JsonObject, Property, Handler
class DateTimeHandler(Handler):
"""
Define a custom handler for datetime objects
"""
def encode(self, obj):
return {
'year' : obj.year,
'month' : obj.month,
'day' : obj.day,
'hour' : obj.hour,
'minute' : obj.minute,
'second' : obj.second,
'microsecond' : obj.microsecond
}
def decode(self, obj_data):
return datetime(**obj_data)
class Entity(JsonObject):
"""
A base class for the object model
"""
oid = Property()
created = Property('created', handler=DateTimeHandler(), default=datetime.now) # Default value when object is instantiated
class Company(Entity):
company_name = Property('company-name') # Specify a different field name in json.
description = Property()
class Sector(Entity):
employees = Property('employees', default=[])
class Employee(Entity):
name = Property()
company = Company(
name='My great company',
description='....'
)
json_data = company.to_dict()
company_2 = Company.from_dict(json_data)
Jsonpickle format support
data = {
'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.
class Company(JsonObject):
company_name = Property('company-name') # Specify a different field name in json.
# Automatically generated getter
company_name = company.get_company_name()
# Also property accessors
company_name = company.company_name
# And private attributes
company_name = company._company_name
Write custom getters and setters
class Company(JsonObject):
company_name = Property('company-name') # Specify a different field name in json.
def get_company_name(self):
print('Getter called!!!')
# generated attribute
return self._company_name
# So, when calling the property getter ...
company_name = company.company_name
# will print 'Getter called!!!'
Enum support
It is possible to decide how to serialize/deserialize enums.
class InvoiceType(Enum):
TYPE_A = 1
TYPE_B = 2
class Invoice(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'
class Invoice(JsonObject):
invoice_type = Property(type=InvoiceType)
invoice = Invoice(invoice_type=InvoiceType.TYPE_A)
serializd = invoice.to_dict()
print(serialized['invoice_type'])
# Will print 1
Json Schema generation.
Check test cases for examples.
Validators.
Check test cases for examples.
Metadata
Release files for podm 0.0.19
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| podm-0.0.19.tar.gz | 21.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| podm-0.0.19-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.1 kB
Release files / podm-0.0.19.tar.gz
| Download URL | podm-0.0.19.tar.gz |
|---|---|
| Size | 21.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73ea8403552edece1691a45aeea271d7551ac265692adc07f03bc2c93d6e6ac9
|
|
BLAKE2b-256 checksum How to use checksums |
902098e16f269bf5fbf9b4840d497d3cc075822aa9b566a94d3c9f7e4c365c71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.0.1 pkginfo/1.7.1 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7
|
Release files / podm-0.0.19-py3-none-any.whl
| Download URL | podm-0.0.19-py3-none-any.whl |
|---|---|
| Size | 29.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7654f7b093b9ebe1ca1e466864f828b47a51082f27132dc6c5ec00cb054a876e
|
|
BLAKE2b-256 checksum How to use checksums |
fc1d6ca68bfae1cb3ec35e61e5db073477ffc00f6dbcced2f4445385f2c6f4c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.2 importlib_metadata/4.0.1 pkginfo/1.7.1 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7
|