Package: jetblack-serialization
jetblack-serializationSerialization for JSON and XML in Python using typing annotations
(read thedocs).StatusIt has been tested with Python 3.7 used thetyping_extensionspackage forTypedDictandAnnotated. In Python 3.8 theTypedDictclass is available in the standardtypingpackage.InstallationThe package can be installed with pip.pipinstalljetblack-serializationOverviewThe package adds support for type annotations when serializing or deserializing
JSON or XML.JSONGiven a typed dictionary:fromdatetimeimportdatetimefromtypingimportList,Optional,TypedDict,UnionclassBook(TypedDict,total=False):book_id:inttitle:strauthor:strpublication_date:datetimekeywords:List[str]phrases:List[str]age:Optional[Union[datetime,int]]pages:Optional[int]SerializingThis could be serialized to JSON as:fromstringcaseimportcamelcase,snakecasefromjetblack_serializationimportSerializerConfigfromjetblack_serialization.jsonimportserializeobj:Book={'author':'Chairman Mao','book_id':42,'title':'Little Red Book','publication_date':datetime(1973,1,1,21,52,13),'keywords':['Revolution','Communism'],'phrases':['Revolutionary wars are inevitable in class society','War is the continuation of politics'],'age':24,}text=serialize(obj,Book,SerializerConfig(camelcase,snakecase,pretty_print=True))print(text)giving:{"bookId":42,"title":"Little Red Book","author":"Chairman Mao","publicationDate":"1973-01-01T21:52:13.00Z","keywords":["Revolution","Communism"],"phrases":["Revolutionary wars are inevitable in class society","War is the continuation of politics"],"age":24,"pages":null}Note the fields have been camel cased, and the publication date has been turned
into an ISO 8601 date.DeserializingWe can deserialize the data as follows:fromstringcaseimportcamelcase,snakecasefromjetblack_serializationimportSerializerConfigfromjetblack_serialization.jsonimportdeserializedct=deserialize(text,Annotated[Book,JSONValue()],SerializerConfig(camelcase,snakecase))XMLThe XML version of the typed dictionary might look like this:fromdatetimeimportdatetimefromtypingimportList,Optional,TypedDict,Unionfromtyping_extensionsimportAnnotatedfromjetblack_serialization.xmlimportXMLEntity,XMLAttributeclassBook(TypedDict,total=False):book_id:Annotated[int,XMLAttribute("bookId")]title:strauthor:strpublication_date:datetimekeywords:Annotated[List[Annotated[str,XMLEntity("Keyword")]],XMLEntity("Keywords")]phrases:List[str]age:Optional[Union[datetime,int]]pages:Optional[int]Note we have introduced some annotations to control the serialization.
For XML we have used pascal-case to serialized the keys and snake-case
for deserialization.SerializingTo serialize we need to provide the containing tagBook:fromstringcaseimportpascalcase,snakecasefromjetblack_serializationimportSerializerConfigfromjetblack_serialization.xmlimportserializebook:Book={'author':'Chairman Mao','book_id':42,'title':'Little Red Book','publication_date':datetime(1973,1,1,21,52,13),'keywords':['Revolution','Communism'],'phrases':['Revolutionary wars are inevitable in class society','War is the continuation of politics'],'age':24,'pages':None}text=serialize(book,Annotated[Book,XMLEntity("Book")],SerializerConfig(pascalcase,snakecase))print(text)Producing:<BookbookId="42"><Title>LittleRedBook</Title><Author>ChairmanMao</Author><PublicationDate>1973-01-01T21:52:13.00Z</PublicationDate><Keywords><Keyword>Revolution</Keyword><Keyword>Communism</Keyword></Keywords><Phrase>Revolutionarywarsareinevitableinclasssociety</Phrase><Phrase>Waristhecontinuationofpolitics</Phrase><Age>24</Age></Book>'The annotations are more elaborate here. However, much of the typed dictionary
requires no annotation.First we needed the outer document wrapperXMLEntity("Book").Next we annotated thebook_idto be anXMLAttribute.Finally we annotated the two lists differently. Thekeywordslist used
a nested structure, which we indicated by giving the list a differentXMLEntitytag to the list items. For the phrases we used the default
in-line behaviour.DeserializingWe can deserialize the XML as follows:fromstringcaseimportpascalcase,snakecasefromjetblack_serializationimportSerializerConfigfromjetblack_serialization.xmlimportdeserializedct=deserialize(text,Annotated[Book,XMLEntity("Book")],SerializerConfig(pascalcase,snakecase))AttributesFor JSON, attributes are typically not required. HoweverJSONProperty(tag: str)andJSONValue()are provided for
completeness.