# type-serialize
[![PyPI](https://img.shields.io/pypi/v/type-serialize?style=flat-square)](https://pypi.org/project/type-serialize/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/type-serialize?style=flat-square)
[![GitHub](https://img.shields.io/github/license/osom8979/type-serialize?style=flat-square)](https://github.com/osom8979/type-serialize)
Serialize with type annotations
## Features
- Supported in Python 3.8 and later.
- Serialize classes without additional code.
- Custom classes
- [@dataclas](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)
- [NamedTuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple)
- [Enum](https://docs.python.org/3/library/enum.html#enum.Enum)
- (Experimental) [numpy.ndarray](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy-ndarray)
- Deserialization using type annotations.
- Compress serialization results: bz2, gzip, lzma, zlib
- No dependencies
## Overview
To pass a custom object to the [json.dumps](https://docs.python.org/3/library/json.html#json.dumps)
and [json.loads](https://docs.python.org/3/library/json.html#json.loads) functions,
there is the following method.
- Expand [json.JSONEncoder](https://docs.python.org/3/library/json.html#json.JSONEncoder)
and [json.JSONDecoder](https://docs.python.org/3/library/json.html#json.JSONDecoder).
- Convert to built-in Python object supported by
[json.JSONEncoder](https://docs.python.org/3/library/json.html#json.JSONEncoder) and
[json.JSONDecoder](https://docs.python.org/3/library/json.html#json.JSONDecoder).
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](https://docs.python.org/3/library/typing.html)**.
(Although the library is complicated; haha...) There are some additional advantages to using this.
- Static type checking using [mypy](https://mypy.readthedocs.io/en/stable/).
- 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
```shell
pip install type-serialize
```
If you want to add [numpy](https://numpy.org/), [orjson](https://github.com/ijl/orjson),
[msgpack](https://msgpack.org/), [pyyaml](https://pyyaml.org/) support:
```shell
pip install type-serialize[full]
```
## Usage
### Serializable python object
```python
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
```python
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
```python
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
```python
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
```python
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.
```python
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](https://github.com/ijl/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](./LICENSE) file for details. In summary,
**type-serialize** is licensed under the **MIT license**.
Raw data
{
"_id": null,
"home_page": "https://github.com/osom8979/type-serialize",
"name": "type-serialize",
"maintainer": "zer0",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "osom8979@gmail.com",
"keywords": "serialize, deserialize",
"author": "zer0",
"author_email": "osom8979@gmail.com",
"download_url": null,
"platform": null,
"description": "# type-serialize\n\n[![PyPI](https://img.shields.io/pypi/v/type-serialize?style=flat-square)](https://pypi.org/project/type-serialize/)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/type-serialize?style=flat-square)\n[![GitHub](https://img.shields.io/github/license/osom8979/type-serialize?style=flat-square)](https://github.com/osom8979/type-serialize)\n\nSerialize with type annotations\n\n## Features\n\n- Supported in Python 3.8 and later.\n- Serialize classes without additional code.\n - Custom classes\n - [@dataclas](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)\n - [NamedTuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple)\n - [Enum](https://docs.python.org/3/library/enum.html#enum.Enum)\n - (Experimental) [numpy.ndarray](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy-ndarray)\n- Deserialization using type annotations.\n- Compress serialization results: bz2, gzip, lzma, zlib\n- No dependencies\n\n## Overview\n\nTo pass a custom object to the [json.dumps](https://docs.python.org/3/library/json.html#json.dumps)\nand [json.loads](https://docs.python.org/3/library/json.html#json.loads) functions,\nthere is the following method.\n\n- Expand [json.JSONEncoder](https://docs.python.org/3/library/json.html#json.JSONEncoder)\n and [json.JSONDecoder](https://docs.python.org/3/library/json.html#json.JSONDecoder).\n- Convert to built-in Python object supported by\n [json.JSONEncoder](https://docs.python.org/3/library/json.html#json.JSONEncoder) and\n [json.JSONDecoder](https://docs.python.org/3/library/json.html#json.JSONDecoder).\n\nBoth methods require additional code and have some problems.\n\n- Problem of not checking symbols when manipulating strings.\n- When adding/deleting/editing a property, all related codes must be changed together.\n- Painful typecasting (as the biggest problem).\n\nAs a way to hide these problems with a library and use serialization and deserialization,\nI chose **[type annotations](https://docs.python.org/3/library/typing.html)**.\n(Although the library is complicated; haha...) There are some additional advantages to using this.\n\n- Static type checking using [mypy](https://mypy.readthedocs.io/en/stable/).\n- Autocomplete in IDE like PyCharm.\n\n### Things to know\n\n- All public fields are serialized.\n- Methods are not serialized.\n- Private fields that start with an underscore (`_`) are not serialized.\n- Members specified with the `@property` decorator are not serialized.\n- When deserializing, all fields must be type-annotated.\n- A value of `None` is ignored by the serialization target.\n- When deserializing, the `__init__` function must have **NO** required arguments.\n- Implement `__serialize__` to override the serialization method.\n- Implement `__deserialize__` to override the deserialization method.\n\n## Installation\n\n```shell\npip install type-serialize\n```\n\nIf you want to add [numpy](https://numpy.org/), [orjson](https://github.com/ijl/orjson),\n[msgpack](https://msgpack.org/), [pyyaml](https://pyyaml.org/) support:\n\n```shell\npip install type-serialize[full]\n```\n\n## Usage\n\n### Serializable python object\n\n```python\nfrom dataclasses import dataclass\nfrom type_serialize import deserialize, serialize\n\n\n@dataclass\nclass Sample:\n field1: str\n field2: int\n\n\ndata = Sample(field1=\"a\", field2=100)\nobj = serialize(data)\nassert isinstance(obj, dict)\nassert obj[\"field1\"] == \"a\"\nassert obj[\"field2\"] == 100\nprint(obj)\n\nresult = deserialize(obj, Sample)\nassert isinstance(result, Sample)\nassert data == result\nprint(result)\n```\n\n### Override serialize and deserialize\n\n```python\nfrom dataclasses import dataclass\nfrom type_serialize import deserialize, serialize\n\n\n@dataclass\nclass Sample:\n value: int\n\n def __serialize__(self):\n return {\"a\": self.value}\n\n def __deserialize__(self, data) -> None:\n self.value = data[\"a\"]\n\n def __init__(self, value=100):\n self.value = value\n\n\ntest = Sample(value=200)\nobj = serialize(test)\nassert isinstance(obj, dict)\nassert obj[\"a\"] == 200\nprint(obj)\n\nresult = deserialize(obj, Sample)\nassert isinstance(result, Sample)\nassert test == result\nprint(result)\n```\n\n### JSON dumps/loads\n\n```python\nfrom dataclasses import dataclass\nfrom type_serialize.json import dumps, loads\n\n@dataclass\nclass Sample:\n field1: str\n field2: int\n\n\ndata = Sample(field1=\"a\", field2=100)\njson_data = dumps(data)\nprint(json_data)\n\nresult = loads(json_data, Sample)\nprint(result)\n```\n\n### MsgPack dumps/loads\n\n```python\nfrom dataclasses import dataclass\nfrom type_serialize.msgpack import dumps, loads\n\n@dataclass\nclass Sample:\n field1: str\n field2: int\n\n\ndata = Sample(field1=\"a\", field2=100)\njson_data = dumps(data)\nprint(json_data)\n\nresult = loads(json_data, Sample)\nprint(result)\n```\n\n### Binary encode/decode\n\n```python\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom typing import Any, List, Optional\n\nfrom type_serialize import decode, encode\n\n\n@dataclass\nclass Sample:\n field1: str\n field2: Optional[str] = None\n field3: Optional[List[int]] = None\n field4: Optional[Any] = None\n field5: Optional[datetime] = None\n\n\ndata = Sample(\n field1=\"a\",\n field3=[0, 1, 2],\n field4={\"k\": 100},\n field5=datetime.now(),\n)\n\nraw = encode(data)\nassert isinstance(raw, bytes)\nassert len(raw) > 0\nprint(raw)\n\nresult = decode(raw, Sample)\nassert isinstance(result, Sample)\nassert data == result\nprint(result)\n```\n\nThe encoding format can be adjusted with the `coding` argument.\n\n```python\nfrom type_serialize import ByteCoding, decode, encode\n\ndata = ...\nprint(encode(data, coding=ByteCoding.MsgpackGzip))\n\nencoded_data = ...\nprint(decode(encoded_data, coding=ByteCoding.OrjsonZlib))\n```\n\n## orjson support\n\nIf [orjson](https://github.com/ijl/orjson) is installed, it is automatically detected and used.\n\nTo turn off this option, set the `TYPE_SERIALIZE_DISABLE_ORJSON_INSTALL` environment variable to `1`.\n\n## License\n\nSee the [LICENSE](./LICENSE) file for details. In summary,\n**type-serialize** is licensed under the **MIT license**.\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "Serialize with type annotations",
"version": "1.3.0",
"project_urls": {
"GitHub: issues": "https://github.com/osom8979/type-serialize/issues",
"GitHub: repo": "https://github.com/osom8979/type-serialize",
"Homepage": "https://github.com/osom8979/type-serialize"
},
"split_keywords": [
"serialize",
" deserialize"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8946743fec8a4c603335151de07adcfda8edca476c68c6f7f37d91c7bce494cd",
"md5": "70a665a5bc967521d64ec2a920927765",
"sha256": "5aeb63a65f44a9b3a1e176573ca3bac27c580e1b750fd435f19b0ffd47771d9e"
},
"downloads": -1,
"filename": "type_serialize-1.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "70a665a5bc967521d64ec2a920927765",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 26662,
"upload_time": "2024-05-13T02:02:46",
"upload_time_iso_8601": "2024-05-13T02:02:46.249126Z",
"url": "https://files.pythonhosted.org/packages/89/46/743fec8a4c603335151de07adcfda8edca476c68c6f7f37d91c7bce494cd/type_serialize-1.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-13 02:02:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "osom8979",
"github_project": "type-serialize",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "type-serialize"
}