python-dataclasses-serialization
python-dataclasses-serialization copied to clipboard
Serialize/deserialize Python dataclasses to various other data formats
dataclasses_serialization
dataclasses_serialization provides serializers/deserializers for transforming between Python dataclasses, and JSON and BSON objects.
Basic Usage
Suppose we have the following dataclass:
from dataclasses import dataclass
@dataclass
class InventoryItem:
name: str
unit_price: float
quantity_on_hand: int
Then we may serialize/deserialize it to/from JSON by using JSONSerializer
>>> from dataclasses_serialization.json import JSONSerializer
>>> JSONSerializer.serialize(InventoryItem("Apple", 0.2, 20))
{'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20}
>>> JSONSerializer.deserialize(InventoryItem, {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20})
InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20)
Mongo
As Mongo collections store objects as BSON, you can use BSONSerializer to dump dataclasses directly into Mongo.
from dataclasses_serialization.bson import BSONSerializer
collection.insert_one(BSONSerializer.serialize(item))
item = BSONSerializer.deserialize(InventoryItem, collection.find_one())
Custom Serializers
To create a custom serializer, create an instance of dataclasses_serialization.serializer_base.Serializer:
from dataclasses_serialization.serializer_base import noop_serialization, noop_deserialization, dict_serialization, dict_deserialization, list_deserialization, Serializer
JSONSerializer = Serializer(
serialization_functions={
dict: lambda dct: dict_serialization(dct, key_serialization_func=JSONSerializer.serialize, value_serialization_func=JSONSerializer.serialize),
list: lambda lst: list(map(JSONSerializer.serialize, lst)),
(str, int, float, bool, type(None)): noop_serialization
},
deserialization_functions={
dict: lambda cls, dct: dict_deserialization(cls, dct, key_deserialization_func=JSONSerializer.deserialize, value_deserialization_func=JSONSerializer.deserialize),
list: lambda cls, lst: list_deserialization(cls, lst, deserialization_func=JSONSerializer.deserialize),
(str, int, float, bool, type(None)): noop_deserialization
}
)
Reference
dataclasses_serialization.serializer_base
A collection of utilities to make it easier to create serializers.
-
isinstance(o, t),issubclass(cls, clsinfo)Extended versions of the builtin
isinstanceandissubclass, to treatdataclassas a superclass for dataclasses, and to be usable with supportedtypingtypes. -
noop_serialization(obj),noop_deserialization(cls, obj)The trivial serialization/deserialization functions, which serialize by doing nothing.
-
dict_to_dataclass(cls, dct, deserialization_func=noop_deserialization)The inverse of
dataclasses.asdict, which deserializes a dictionarydctto a dataclasscls, usingdeserialization_functo deserialize the fields ofcls.Fields are deserialized using the type provided by the dataclass. So bound generic dataclasses may be deserialized, while unbound ones may not.
-
union_deserialization(type_, obj, deserialization_func=noop_deserialization)Deserialize a
Uniontype_, by trying each type in turn, and returning the first that does not raise aDeserializationError.As
Optionals are implemented asUnions, this function also works for them. -
dict_serialization(obj, key_serialization_func=noop_serialization, value_serialization_func=noop_serialization),dict_deserialization(type_, obj, key_deserialization_func=noop_deserialization, value_deserialization_func=noop_deserialization)Serialize/deserialize a dictionary
objby applying the appropriate serialization/deserialization functions to keys and values. -
list_deserialization(type_, obj, deserialization_func=noop_deserialization)Deserialize a list
objby applying the deserialization function to its values. -
Serializer(serialization_functions, deserialization_functions)The general serialization class.
Takes two dictionaries of serialization and deserialization functions, and defers to them appropriately when serializing/deserializing and object by the
serializeanddeserializemethods. Serializer functions take a single parameter, the object to be serialized, and returns a serialized version of it. Deserializer functions take two parameters, the desired type of the deserialized object, and the object to be deserialized.If an object's type cannot be found directly in the serialization/deserialization functions, the
Serializeruses its closest ancestor - raising an error in case of ambiguity.By default
dataclasses are serialized as though they aredicts. Similarly,dataclasses are deserialized usingdict_to_dataclass, andUnions usingunion_deserialization, using itself as the nested deserialization function.Serialize a Python object with
serializer.serialize(obj), and deserialize withserializer.deserialize(cls, serialized_obj).Register more serialization/deserialization functions with
serializer.register_serializer(cls, func),serializer.register_deserializer(cls, func), andserializer.register(cls, serialization_func, deserialization_func). They can also be used as decorators like so:@serializer.register_serializer(int) def int_serializer(obj): ...@serializer.register_deserializer(int) def int_deserializer(cls, obj): ... -
SerializationError,DeserializationErrorErrors to be raised when serialization/deserialization fails, respectively.
dataclasses_serialization.json
-
JSONSerializerSerializer/deserializer between Python dataclasses and JSON objects.
>>> JSONSerializer.serialize(InventoryItem("Apple", 0.2, 20)) {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20} >>> JSONSerializer.deserialize(InventoryItem, {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20}) InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20) -
JSONSerializerMixinAdds
as_jsonandfrom_jsonmethods to dataclasses when used as a mixin.@dataclass class InventoryItem(JSONSerializerMixin): ...>>> InventoryItem("Apple", 0.2, 20).as_json() {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20} >>> InventoryItem.from_json({'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20}) InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20) -
JSONStrSerializerSerializer/deserializer between Python dataclasses and JSON strings.
>>> JSONStrSerializer.serialize(InventoryItem("Apple", 0.2, 20)) '{"name": "Apple", "unit_price": 0.2, "quantity_on_hand": 20}' >>> JSONStrSerializer.deserialize(InventoryItem, '{"name": "Apple", "unit_price": 0.2, "quantity_on_hand": 20}') InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20) -
JSONStrSerializerMixinAdds
as_json_strandfrom_json_strmethods to dataclasses when used as a mixin.@dataclass class InventoryItem(JSONStrSerializerMixin): ...>>> InventoryItem("Apple", 0.2, 20).as_json_str() '{"name": "Apple", "unit_price": 0.2, "quantity_on_hand": 20}' >>> InventoryItem.from_json_str('{"name": "Apple", "unit_price": 0.2, "quantity_on_hand": 20}') InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20)
dataclasses_serialization.bson
-
BSONSerializerSerializer/deserializer between Python dataclasses and BSON objects.
>>> BSONSerializer.serialize(InventoryItem("Apple", 0.2, 20)) {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20} >>> BSONSerializer.deserialize(InventoryItem, {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20}) InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20) -
BSONSerializerMixinAdds
as_bsonandfrom_bsonmethods to dataclasses when used as a mixin.@dataclass class InventoryItem(BSONSerializerMixin): ...>>> InventoryItem("Apple", 0.2, 20).as_bson() {'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20} >>> InventoryItem.from_bson({'name': 'Apple', 'unit_price': 0.2, 'quantity_on_hand': 20}) InventoryItem(name='Apple', unit_price=0.2, quantity_on_hand=20) -
BSONStrSerializerSerializer/deserializer between Python dataclasses and binary BSON strings.
-
BSONStrSerializerMixinAdds
as_bson_strandfrom_bson_strmethods to dataclasses when used as a mixin.@dataclass class InventoryItem(BSONStrSerializerMixin): ...
Installation
Install and update using the standard Python package manager pip:
pip install dataclasses_serialization