Package: pyjo
pyjoPython JSON ObjectsEasily specify and (de)serialize data models in Python.Installpip install pyjoHow to useFirst you need to create a specification of your models and attributes by using theModeland theFieldclasses:frompyjoimportModel,Field,RangeField,EnumFieldclassGender(Enum):female=0male=1classAddress(Model):city=Field(type=str)postal_code=Field(type=int)address=Field()classUser(Model):name=Field(type=str,repr=True,required=True)age=RangeField(min=18,max=120)#  equivalent to: Field(type=int, validator=lambda x: 18 <= x <= 120)gender=EnumField(enum=Gender)address=Field(type=Address)By default any field is considered optional unless specified withrequiredattribute. If required, its presence will be checked during initialization.u=User()# ...# pyjo.exceptions.RequiredField: Field 'name' is requiredUser(name='john',age=18,address=Address(city='NYC'))# <User(name=john)>When thetypeargument is provided, the type of the value assigned to a field will be checked during initialization and assignment:User(name=123)# ...# pyjo.exceptions.InvalidType: The value of the field 'name' is not of type str, given 123u.address.city=1# ...# pyjo.exceptions.InvalidType: The value of the field 'city' is not of type str, given 1In order to serialize a model you need to callto_dict:u=User(name='john',age=18,address=Address(city='NYC'))print(u.to_dict())# {#     "name": "john",#     "age": 18,#     "address": {#         "city": "NYC"#     }# }To create a model starting from its python dictionary representation, usefrom_dict:u=User.from_dict({"name":"john","gender":"male","age":18,"address":{"city":"NYC"}})print(u)# <User(name=john)>print(u.gender)# Gender.maleprint(u.address.city)# NYCNote thatfrom_dictwill also recreate all the nested pyjo objects.API DocumentationFieldTheFieldobject has severaloptionalarguments:typespecifies the type of the field. If specified, the type will be checked during initialization and assignmentdefaultspecifies the default value for the field. The value of a default can be a function and it will be computed and assigned during the initialization of the objectrequiredboolean flag to indicate if the field must be specified and can't beNone, even during assignment (Falseby default)reprboolean flag to indicate if the field/value should be shown in the Python representation of the object, when printed (Falseby default)to_dict,from_dict(functions) to add ad-hoc serialization/deserialization for the fieldvalidator(function) function that gets called to validate the input (after cast) of a fieldcast(function) cast value of the field (if not empty) before (validation and) assignmentModelto_dict(),from_dict()serialize/deserialize to/from python dictionariesto_json(),from_json()shortcuts forjson.dumps(model.to_dict())andModel.from_dict(json.loads(<dict>))Field subclassesYou can easily create subclasses ofFieldto handle specific types of objects. Several of them are already integrated in pyjo and more are coming (feel free to create a PR to add more):ListFieldfor fields containing a list of elementsRegexFieldfor fields containing a string that matches a given regexRangeFieldfor fields containing a int with optional minimum/maximum valueDatetimeFieldfor fields containing a UTC datetimeExtensionspyjo_mongoeasily interact with MongoDB documents, a lightweight replacement of themongoenginelibrary