Skip to content

osom8979/type-serialize

Repository files navigation

type-serialize

PyPI PyPI - Python Version GitHub

Serialize with type annotations

Features

  • Supported in Python 3.8 and later.
  • Serialize classes without additional code.
  • Deserialization using type annotations.
  • Compress serialization results: bz2, gzip, lzma, zlib
  • No dependencies

Overview

To pass a custom object to the json.dumps and json.loads functions, there is the following method.

Both methods require additional code and have some problems.

  • Problem of not checking symbols when manipulating strings.
  • When adding/deleting/editing a property, all related codes must be changed together.
  • Painful typecasting (as the biggest problem).

As a way to hide these problems with a library and use serialization and deserialization, I chose type annotations. (Although the library is complicated; haha...) There are some additional advantages to using this.

  • Static type checking using mypy.
  • Autocomplete in IDE like PyCharm.

Things to know

  • All public fields are serialized.
  • Methods are not serialized.
  • Private fields that start with an underscore (_) are not serialized.
  • Members specified with the @property decorator are not serialized.
  • When deserializing, all fields must be type-annotated.
  • A value of None is ignored by the serialization target.
  • When deserializing, the __init__ function must have NO required arguments.
  • Implement __serialize__ to override the serialization method.
  • Implement __deserialize__ to override the deserialization method.

Installation

pip install type-serialize

If you want to add numpy, orjson, msgpack, pyyaml support:

pip install type-serialize[full]

Usage

Serializable python object

from dataclasses import dataclass
from type_serialize import deserialize, serialize


@dataclass
class Sample:
    field1: str
    field2: int


data = Sample(field1="a", field2=100)
obj = serialize(data)
assert isinstance(obj, dict)
assert obj["field1"] == "a"
assert obj["field2"] == 100
print(obj)

result = deserialize(obj, Sample)
assert isinstance(result, Sample)
assert data == result
print(result)

Override serialize and deserialize

from dataclasses import dataclass
from type_serialize import deserialize, serialize


@dataclass
class Sample:
    value: int

    def __serialize__(self):
        return {"a": self.value}

    def __deserialize__(self, data) -> None:
        self.value = data["a"]

    def __init__(self, value=100):
        self.value = value


test = Sample(value=200)
obj = serialize(test)
assert isinstance(obj, dict)
assert obj["a"] == 200
print(obj)

result = deserialize(obj, Sample)
assert isinstance(result, Sample)
assert test == result
print(result)

JSON dumps/loads

from dataclasses import dataclass
from type_serialize.json import dumps, loads

@dataclass
class Sample:
    field1: str
    field2: int


data = Sample(field1="a", field2=100)
json_data = dumps(data)
print(json_data)

result = loads(json_data, Sample)
print(result)

MsgPack dumps/loads

from dataclasses import dataclass
from type_serialize.msgpack import dumps, loads

@dataclass
class Sample:
    field1: str
    field2: int


data = Sample(field1="a", field2=100)
json_data = dumps(data)
print(json_data)

result = loads(json_data, Sample)
print(result)

Binary encode/decode

from dataclasses import dataclass
from datetime import datetime
from typing import Any, List, Optional

from type_serialize import decode, encode


@dataclass
class Sample:
    field1: str
    field2: Optional[str] = None
    field3: Optional[List[int]] = None
    field4: Optional[Any] = None
    field5: Optional[datetime] = None


data = Sample(
    field1="a",
    field3=[0, 1, 2],
    field4={"k": 100},
    field5=datetime.now(),
)

raw = encode(data)
assert isinstance(raw, bytes)
assert len(raw) > 0
print(raw)

result = decode(raw, Sample)
assert isinstance(result, Sample)
assert data == result
print(result)

The encoding format can be adjusted with the coding argument.

from type_serialize import ByteCoding, decode, encode

data = ...
print(encode(data, coding=ByteCoding.MsgpackGzip))

encoded_data = ...
print(decode(encoded_data, coding=ByteCoding.OrjsonZlib))

orjson support

If orjson is installed, it is automatically detected and used.

To turn off this option, set the TYPE_SERIALIZE_DISABLE_ORJSON_INSTALL environment variable to 1.

License

See the LICENSE file for details. In summary, type-serialize is licensed under the MIT license.