drf-serpy


Namedrf-serpy JSON
Version 0.5.0 PyPI version JSON
download
home_page
SummaryRidiculously fast object serialization
upload_time2024-01-06 14:21:44
maintainer
docs_urlNone
authorSergen Pekşen
requires_python>=3.6,<4.0
licenseMIT
keywords serialization rest json api marshal marshalling validation schema fast
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## drf-serpy: ridiculously fast object serialization

[![Travis-CI](https://travis-ci.org/clarkduvall/serpy.svg?branch=master)](https://travis-ci.org/clarkduvall/serpy?branch=master)

[![Coveralls](https://coveralls.io/repos/clarkduvall/serpy/badge.svg?branch=master)](https://coveralls.io/r/clarkduvall/serpy?branch=master)

[![Documentation Status](https://readthedocs.org/projects/drf-serpy/badge/?version=latest)](https://readthedocs.org/projects/drf-serpy/?badge=latest)

[![PyPI version](https://badge.fury.io/py/drf-serpy.svg)](https://badge.fury.io/py/drf-serpy)

**drf-serpy** is a super simple object serialization framework built for speed. **drf-serpy** serializes complex datatypes (Django Models, custom classes, ...) to simple native types (dicts, lists, strings, ...). The native types can easily be converted to JSON or any other format needed.

The goal of **drf-serpy** is to be able to do this *simply*, *reliably*, and *quickly*. Since serializers are class based, they can be combined, extended and customized with very little code duplication. This project aims to replace the DRF serializer in terms of *deserialization*.

 Compared to other popular Python serialization frameworks like [Django Rest Framework Serializers](http://www.django-rest-framework.org/api-guide/serializers/)
**drf-serpy** is at least an [order of magnitude](http://serpy.readthedocs.org/en/latest/performance.html)
faster.

Source
------

Source at: <https://github.com/sergenp/drf-serpy>

If you want a feature, send a pull request!

Documentation
-------------

Full documentation at: <https://drf-serpy.readthedocs.io/en/latest/>

Installation
------------

Note that this project is aimed for **Django Rest Framework** and does not intend to provide deserialization to other frameworks. Original [serpy](https://github.com/clarkduvall/serpy) repository can be used for such cases. This is mainly because of the added *drf-yasg* for swagger generation for the *drf-serpy serializers*.

```bash
$ pip install drf-serpy
```

Examples
--------

### Simple Example

```python
import drf_serpy as serpy

class Foo(object):
    """The object to be serialized."""
    y = 'hello'
    z = 9.5

    def __init__(self, x):
        self.x = x


class FooSerializer(serpy.Serializer):
    """The serializer schema definition."""
    # Use a Field subclass like IntField if you need more validation.
    x = serpy.IntField()
    y = serpy.Field()
    z = serpy.Field()

f = Foo(1)
FooSerializer(f).data
# {'x': 1, 'y': 'hello', 'z': 9.5}

fs = [Foo(i) for i in range(100)]
FooSerializer(fs, many=True).data
# [{'x': 0, 'y': 'hello', 'z': 9.5}, {'x': 1, 'y': 'hello', 'z': 9.5}, ...]
```

### Nested Example

```python
import drf_serpy as serpy

class Nestee(object):
    """An object nested inside another object."""
    n = 'hi'


class Foo(object):
    x = 1
    nested = Nestee()


class NesteeSerializer(serpy.Serializer):
    n = serpy.Field()


class FooSerializer(serpy.Serializer):
    x = serpy.Field()
    # Use another serializer as a field.
    nested = NesteeSerializer()

f = Foo()
FooSerializer(f).data
# {'x': 1, 'nested': {'n': 'hi'}}
```

### Complex Example

```python
import drf_serpy as serpy

class Foo(object):
    y = 1
    z = 2
    super_long_thing = 10

    def x(self):
        return 5


class FooSerializer(serpy.Serializer):
    w = serpy.Field(attr='super_long_thing')
    x = serpy.Field(call=True)
    plus = serpy.MethodField()

    def get_plus(self, obj):
        return obj.y + obj.z

f = Foo()
FooSerializer(f).data
# {'w': 10, 'x': 5, 'plus': 3}
```

### Inheritance Example

```python
import drf_serpy as serpy

class Foo(object):
    a = 1
    b = 2


class ASerializer(serpy.Serializer):
    a = serpy.Field()


class ABSerializer(ASerializer):
    """ABSerializer inherits the 'a' field from ASerializer.

    This also works with multiple inheritance and mixins.
    """
    b = serpy.Field()

f = Foo()
ASerializer(f).data
# {'a': 1}
ABSerializer(f).data
# {'a': 1, 'b': 2}
```

### Swagger Generation Example 

Example is available in test_django_app, you can run the app after
cloning the project.

```python
python test_django_app/manage.py runserver
```

Note that the swagger generation is for `drf_serpy.Serializer` and doesn't care about the inputted model.
i.e. the `openapi.Schema` will be generated based on the serializer attributes.

```python
import drf_serpy as serpy
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from .models import Post 
from .serializers import drf, serps

# serps.ReadOnlyPostSerializer is this:
# class ReadOnlyPostSerializer(serpy.Serializer):
#     """
#     Sample description to be used in schema
#     """
#     id = serpy.IntField()
#     author = UserSerializer()
#     title = serpy.StrField()
#     content = serpy.StrField()
#     image = serpy.ImageField()
#     tags = TagSerializer(many=True)
#     created = serpy.DateTimeField()
#     updated = serpy.DateTimeField()
#     dummy = serpy.MethodField()
#     is_completed = serpy.MethodField()

#     def get_dummy(self, value) -> List[int]:
#         return list(range(1, 10))

#     # typing is necessary to create schema, otherwise this will throw an assertion error
#     def get_is_completed(self, value) -> bool:
#         return True

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = drf.PostSerializer

    @swagger_auto_schema(
        responses={
            200: ReadOnlyPostSerializer.to_schema(many=True),
        },
    )
    def list(self, request, *args, **kwargs):
        # get your objects
        serializer = serps.ReadOnlyPostSerializer(instance=self.queryset.all(), many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)
```

Generated Swagger:
![Swagger Gen](https://drf-serpy.readthedocs.io/en/latest/imgs/swagger_gen.png)

#### Generic serializer swagger generation example:

```python

# class CommentSerializer(drf_serpy.Serializer):
#     id = drf_serpy.IntField()
#     user = UserSerializer()
#     post = ReadOnlyPostSerializer()
#     comment = drf_serpy.StrField()
#     created = drf_serpy.DateTimeField()
#     updated = drf_serpy.DateTimeField()


# class LinkSerializer(drf_serpy.Serializer):
#     next = drf_serpy.StrField()
#     previous = drf_serpy.StrField()


# class PaginationSerializer(drf_serpy.Serializer):
#     links = LinkSerializer()
#     count = drf_serpy.IntField()
#     current_page = drf_serpy.IntField()
#     page_size = drf_serpy.IntField()
#     results = drf_serpy.Serializer()

class CommentViewSet(ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = drf.CommentSerializer

    @swagger_auto_schema(
        responses={
            200: PaginationSerializer.to_schema(serializer=CommentSerializer(many=True)),
        },
    )
    def list(self, request, *args, **kwargs):
        self.serializer_class = serps.CommentSerializer
        return super().list(request, *args, **kwargs)
```
    
Generated Swagger:

![Swagger Gen Pagination](https://drf-serpy.readthedocs.io/en/latest/imgs/swagger_gen_pagination.png)


License
-------

drf-serpy is free software distributed under the terms of the MIT license.
See the [LICENSE](https://github.com/sergenp/drf-serpy/blob/master/LICENSE) file.


            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "drf-serpy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6,<4.0",
    "maintainer_email": "",
    "keywords": "serialization,rest,json,api,marshal,marshalling,validation,schema,fast",
    "author": "Sergen Pek\u015fen",
    "author_email": "speksen@kb01.ai",
    "download_url": "https://files.pythonhosted.org/packages/73/10/7cae63bf509b5ad00a3d1c709ff718f53088ccb2f4c676647a87a43016a7/drf_serpy-0.5.0.tar.gz",
    "platform": null,
    "description": "## drf-serpy: ridiculously fast object serialization\n\n[![Travis-CI](https://travis-ci.org/clarkduvall/serpy.svg?branch=master)](https://travis-ci.org/clarkduvall/serpy?branch=master)\n\n[![Coveralls](https://coveralls.io/repos/clarkduvall/serpy/badge.svg?branch=master)](https://coveralls.io/r/clarkduvall/serpy?branch=master)\n\n[![Documentation Status](https://readthedocs.org/projects/drf-serpy/badge/?version=latest)](https://readthedocs.org/projects/drf-serpy/?badge=latest)\n\n[![PyPI version](https://badge.fury.io/py/drf-serpy.svg)](https://badge.fury.io/py/drf-serpy)\n\n**drf-serpy** is a super simple object serialization framework built for speed. **drf-serpy** serializes complex datatypes (Django Models, custom classes, ...) to simple native types (dicts, lists, strings, ...). The native types can easily be converted to JSON or any other format needed.\n\nThe goal of **drf-serpy** is to be able to do this *simply*, *reliably*, and *quickly*. Since serializers are class based, they can be combined, extended and customized with very little code duplication. This project aims to replace the DRF serializer in terms of *deserialization*.\n\n Compared to other popular Python serialization frameworks like [Django Rest Framework Serializers](http://www.django-rest-framework.org/api-guide/serializers/)\n**drf-serpy** is at least an [order of magnitude](http://serpy.readthedocs.org/en/latest/performance.html)\nfaster.\n\nSource\n------\n\nSource at: <https://github.com/sergenp/drf-serpy>\n\nIf you want a feature, send a pull request!\n\nDocumentation\n-------------\n\nFull documentation at: <https://drf-serpy.readthedocs.io/en/latest/>\n\nInstallation\n------------\n\nNote that this project is aimed for **Django Rest Framework** and does not intend to provide deserialization to other frameworks. Original [serpy](https://github.com/clarkduvall/serpy) repository can be used for such cases. This is mainly because of the added *drf-yasg* for swagger generation for the *drf-serpy serializers*.\n\n```bash\n$ pip install drf-serpy\n```\n\nExamples\n--------\n\n### Simple Example\n\n```python\nimport drf_serpy as serpy\n\nclass Foo(object):\n    \"\"\"The object to be serialized.\"\"\"\n    y = 'hello'\n    z = 9.5\n\n    def __init__(self, x):\n        self.x = x\n\n\nclass FooSerializer(serpy.Serializer):\n    \"\"\"The serializer schema definition.\"\"\"\n    # Use a Field subclass like IntField if you need more validation.\n    x = serpy.IntField()\n    y = serpy.Field()\n    z = serpy.Field()\n\nf = Foo(1)\nFooSerializer(f).data\n# {'x': 1, 'y': 'hello', 'z': 9.5}\n\nfs = [Foo(i) for i in range(100)]\nFooSerializer(fs, many=True).data\n# [{'x': 0, 'y': 'hello', 'z': 9.5}, {'x': 1, 'y': 'hello', 'z': 9.5}, ...]\n```\n\n### Nested Example\n\n```python\nimport drf_serpy as serpy\n\nclass Nestee(object):\n    \"\"\"An object nested inside another object.\"\"\"\n    n = 'hi'\n\n\nclass Foo(object):\n    x = 1\n    nested = Nestee()\n\n\nclass NesteeSerializer(serpy.Serializer):\n    n = serpy.Field()\n\n\nclass FooSerializer(serpy.Serializer):\n    x = serpy.Field()\n    # Use another serializer as a field.\n    nested = NesteeSerializer()\n\nf = Foo()\nFooSerializer(f).data\n# {'x': 1, 'nested': {'n': 'hi'}}\n```\n\n### Complex Example\n\n```python\nimport drf_serpy as serpy\n\nclass Foo(object):\n    y = 1\n    z = 2\n    super_long_thing = 10\n\n    def x(self):\n        return 5\n\n\nclass FooSerializer(serpy.Serializer):\n    w = serpy.Field(attr='super_long_thing')\n    x = serpy.Field(call=True)\n    plus = serpy.MethodField()\n\n    def get_plus(self, obj):\n        return obj.y + obj.z\n\nf = Foo()\nFooSerializer(f).data\n# {'w': 10, 'x': 5, 'plus': 3}\n```\n\n### Inheritance Example\n\n```python\nimport drf_serpy as serpy\n\nclass Foo(object):\n    a = 1\n    b = 2\n\n\nclass ASerializer(serpy.Serializer):\n    a = serpy.Field()\n\n\nclass ABSerializer(ASerializer):\n    \"\"\"ABSerializer inherits the 'a' field from ASerializer.\n\n    This also works with multiple inheritance and mixins.\n    \"\"\"\n    b = serpy.Field()\n\nf = Foo()\nASerializer(f).data\n# {'a': 1}\nABSerializer(f).data\n# {'a': 1, 'b': 2}\n```\n\n### Swagger Generation Example \n\nExample is available in test_django_app, you can run the app after\ncloning the project.\n\n```python\npython test_django_app/manage.py runserver\n```\n\nNote that the swagger generation is for `drf_serpy.Serializer` and doesn't care about the inputted model.\ni.e. the `openapi.Schema` will be generated based on the serializer attributes.\n\n```python\nimport drf_serpy as serpy\nfrom drf_yasg.utils import swagger_auto_schema\nfrom rest_framework import status\nfrom rest_framework.response import Response\nfrom rest_framework.viewsets import ModelViewSet\n\nfrom .models import Post \nfrom .serializers import drf, serps\n\n# serps.ReadOnlyPostSerializer is this:\n# class ReadOnlyPostSerializer(serpy.Serializer):\n#     \"\"\"\n#     Sample description to be used in schema\n#     \"\"\"\n#     id = serpy.IntField()\n#     author = UserSerializer()\n#     title = serpy.StrField()\n#     content = serpy.StrField()\n#     image = serpy.ImageField()\n#     tags = TagSerializer(many=True)\n#     created = serpy.DateTimeField()\n#     updated = serpy.DateTimeField()\n#     dummy = serpy.MethodField()\n#     is_completed = serpy.MethodField()\n\n#     def get_dummy(self, value) -> List[int]:\n#         return list(range(1, 10))\n\n#     # typing is necessary to create schema, otherwise this will throw an assertion error\n#     def get_is_completed(self, value) -> bool:\n#         return True\n\nclass PostViewSet(ModelViewSet):\n    queryset = Post.objects.all()\n    serializer_class = drf.PostSerializer\n\n    @swagger_auto_schema(\n        responses={\n            200: ReadOnlyPostSerializer.to_schema(many=True),\n        },\n    )\n    def list(self, request, *args, **kwargs):\n        # get your objects\n        serializer = serps.ReadOnlyPostSerializer(instance=self.queryset.all(), many=True)\n        return Response(data=serializer.data, status=status.HTTP_200_OK)\n```\n\nGenerated Swagger:\n![Swagger Gen](https://drf-serpy.readthedocs.io/en/latest/imgs/swagger_gen.png)\n\n#### Generic serializer swagger generation example:\n\n```python\n\n# class CommentSerializer(drf_serpy.Serializer):\n#     id = drf_serpy.IntField()\n#     user = UserSerializer()\n#     post = ReadOnlyPostSerializer()\n#     comment = drf_serpy.StrField()\n#     created = drf_serpy.DateTimeField()\n#     updated = drf_serpy.DateTimeField()\n\n\n# class LinkSerializer(drf_serpy.Serializer):\n#     next = drf_serpy.StrField()\n#     previous = drf_serpy.StrField()\n\n\n# class PaginationSerializer(drf_serpy.Serializer):\n#     links = LinkSerializer()\n#     count = drf_serpy.IntField()\n#     current_page = drf_serpy.IntField()\n#     page_size = drf_serpy.IntField()\n#     results = drf_serpy.Serializer()\n\nclass CommentViewSet(ModelViewSet):\n    queryset = Comment.objects.all()\n    serializer_class = drf.CommentSerializer\n\n    @swagger_auto_schema(\n        responses={\n            200: PaginationSerializer.to_schema(serializer=CommentSerializer(many=True)),\n        },\n    )\n    def list(self, request, *args, **kwargs):\n        self.serializer_class = serps.CommentSerializer\n        return super().list(request, *args, **kwargs)\n```\n    \nGenerated Swagger:\n\n![Swagger Gen Pagination](https://drf-serpy.readthedocs.io/en/latest/imgs/swagger_gen_pagination.png)\n\n\nLicense\n-------\n\ndrf-serpy is free software distributed under the terms of the MIT license.\nSee the [LICENSE](https://github.com/sergenp/drf-serpy/blob/master/LICENSE) file.\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Ridiculously fast object serialization",
    "version": "0.5.0",
    "project_urls": null,
    "split_keywords": [
        "serialization",
        "rest",
        "json",
        "api",
        "marshal",
        "marshalling",
        "validation",
        "schema",
        "fast"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9c966e186e98a34d7a624c464576064338cd0d663a038143c1ccdc59e51314ae",
                "md5": "e8f81a44559091c8eed903bf9bd55f9e",
                "sha256": "a34cca9265e08582777151a70226ed92fe2df9cac2d2905e4e6748d5107d4688"
            },
            "downloads": -1,
            "filename": "drf_serpy-0.5.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e8f81a44559091c8eed903bf9bd55f9e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6,<4.0",
            "size": 10624,
            "upload_time": "2024-01-06T14:21:43",
            "upload_time_iso_8601": "2024-01-06T14:21:43.312863Z",
            "url": "https://files.pythonhosted.org/packages/9c/96/6e186e98a34d7a624c464576064338cd0d663a038143c1ccdc59e51314ae/drf_serpy-0.5.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "73107cae63bf509b5ad00a3d1c709ff718f53088ccb2f4c676647a87a43016a7",
                "md5": "d43ff3ca24cf3bab1b91090fb568e3bd",
                "sha256": "b98db518f7431cead169d168b072067123462f4060164a97c65657a0e95ccd0a"
            },
            "downloads": -1,
            "filename": "drf_serpy-0.5.0.tar.gz",
            "has_sig": false,
            "md5_digest": "d43ff3ca24cf3bab1b91090fb568e3bd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6,<4.0",
            "size": 11725,
            "upload_time": "2024-01-06T14:21:44",
            "upload_time_iso_8601": "2024-01-06T14:21:44.766284Z",
            "url": "https://files.pythonhosted.org/packages/73/10/7cae63bf509b5ad00a3d1c709ff718f53088ccb2f4c676647a87a43016a7/drf_serpy-0.5.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-06 14:21:44",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "drf-serpy"
}
        
Elapsed time: 0.17682s