Skip to main content

Ridiculously fast object serialization

Project description

drf-serpy: ridiculously fast object serialization

Travis-CI

Coveralls

Documentation Status

PyPI version

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 drf-serpy is at least an order of magnitude 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 repository can be used for such cases. This is mainly because of the added drf-yasg for swagger generation for the drf-serpy serializers.

$ pip install drf-serpy

Examples

Simple Example

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

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

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

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 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.

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

Generic serializer swagger generation example:

# 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

License

drf-serpy is free software distributed under the terms of the MIT license. See the LICENSE file.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_serpy-0.5.0.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

drf_serpy-0.5.0-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file drf_serpy-0.5.0.tar.gz.

File metadata

  • Download URL: drf_serpy-0.5.0.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.5

File hashes

Hashes for drf_serpy-0.5.0.tar.gz
Algorithm Hash digest
SHA256 b98db518f7431cead169d168b072067123462f4060164a97c65657a0e95ccd0a
MD5 d43ff3ca24cf3bab1b91090fb568e3bd
BLAKE2b-256 73107cae63bf509b5ad00a3d1c709ff718f53088ccb2f4c676647a87a43016a7

See more details on using hashes here.

File details

Details for the file drf_serpy-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: drf_serpy-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.5

File hashes

Hashes for drf_serpy-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a34cca9265e08582777151a70226ed92fe2df9cac2d2905e4e6748d5107d4688
MD5 e8f81a44559091c8eed903bf9bd55f9e
BLAKE2b-256 9c966e186e98a34d7a624c464576064338cd0d663a038143c1ccdc59e51314ae

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page