Serialization for JSON and XML using typing
Project description
jetblack-serialization
Serialization for JSON and XML in Python using typing annotations (read the docs).
Status
It has been tested with Python 3.7 used the typing_extensions
package for TypedDict
and Annotated
. In Python 3.8 the TypedDict
class is available in the standard typing
package.
Installation
The package can be installed with pip.
pip install jetblack-serialization
Overview
The package adds support for type annotations when serializing or deserializing JSON or XML.
JSON
Given a typed dictionary:
from datetime import datetime
from typing import List, Optional, TypedDict, Union
class Book(TypedDict, total=False):
book_id: int
title: str
author: str
publication_date: datetime
keywords: List[str]
phrases: List[str]
age: Optional[Union[datetime, int]]
pages: Optional[int]
Serializing
This could be serialized to JSON as:
from stringcase import camelcase, snakecase
from jetblack_serialization import SerializerConfig
from jetblack_serialization.json import serialize
obj: 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.
Deserializing
We can deserialize the data as follows:
from stringcase import camelcase, snakecase
from jetblack_serialization import SerializerConfig
from jetblack_serialization.json import deserialize
dct = deserialize(
text,
Annotated[Book, JSONValue()],
SerializerConfig(camelcase, snakecase)
)
XML
The XML version of the typed dictionary might look like this:
from datetime import datetime
from typing import List, Optional, TypedDict, Union
from typing_extensions import Annotated
from jetblack_serialization.xml import XMLEntity, XMLAttribute
class Book(TypedDict, total=False):
book_id: Annotated[int, XMLAttribute("bookId")]
title: str
author: str
publication_date: datetime
keywords: 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.
Serializing
To serialize we need to provide the containing tag Book
:
from stringcase import pascalcase, snakecase
from jetblack_serialization import SerializerConfig
from jetblack_serialization.xml import serialize
book: 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:
<Book bookId="42">
<Title>Little Red Book</Title>
<Author>Chairman Mao</Author>
<PublicationDate>1973-01-01T21:52:13.00Z</PublicationDate>
<Keywords>
<Keyword>Revolution</Keyword>
<Keyword>Communism</Keyword>
</Keywords>
<Phrase>Revolutionary wars are inevitable in class society</Phrase>
<Phrase>War is the continuation of politics</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 wrapper XMLEntity("Book")
.
Next we annotated the book_id
to be an XMLAttribute
.
Finally we annotated the two lists differently. The keywords
list used
a nested structure, which we indicated by giving the list a different
XMLEntity
tag to the list items. For the phrases we used the default
in-line behaviour.
Deserializing
We can deserialize the XML as follows:
from stringcase import pascalcase, snakecase
from jetblack_serialization import SerializerConfig
from jetblack_serialization.xml import deserialize
dct = deserialize(
text,
Annotated[Book, XMLEntity("Book")],
SerializerConfig(pascalcase, snakecase)
)
Attributes
For JSON, attributes are typically not required. However
JSONProperty(tag: str)
and JSONValue()
are provided for
completeness.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for jetblack-serialization-2.0.2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1a19f1dd86b6dc1678e748a60f91426bb8c10ddf0cae7c85eeded8e128f70358 |
|
MD5 | d082a2881b7f11551c5d8f07fbaf70dc |
|
BLAKE2b-256 | 7722a07aeb193e1035d58b757b9a34596b4eafdce0ab97f424ed301a8ec88391 |
Hashes for jetblack_serialization-2.0.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e8fa7e175335885b0150e3090f854b25d818a19a39a031081862815e706b131e |
|
MD5 | f550cae0510e89e56c4817ce5f3ee736 |
|
BLAKE2b-256 | 9ac0b17618318fc50fe974905ee04b3cdc9236892c2984127303b5b397a25667 |