drf-serpy: ridiculously fast object serialization
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:
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:
License
drf-serpy is free software distributed under the terms of the MIT license. See the LICENSE file.
Metadata
Release files for drf-serpy 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| drf_serpy-0.5.0.tar.gz | 11.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| drf_serpy-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.3 kB
Release files / drf_serpy-0.5.0.tar.gz
| Download URL | drf_serpy-0.5.0.tar.gz |
|---|---|
| Size | 11.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b98db518f7431cead169d168b072067123462f4060164a97c65657a0e95ccd0a
|
|
BLAKE2b-256 checksum How to use checksums |
73107cae63bf509b5ad00a3d1c709ff718f53088ccb2f4c676647a87a43016a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.5
|
Release files / drf_serpy-0.5.0-py3-none-any.whl
| Download URL | drf_serpy-0.5.0-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a34cca9265e08582777151a70226ed92fe2df9cac2d2905e4e6748d5107d4688
|
|
BLAKE2b-256 checksum How to use checksums |
9c966e186e98a34d7a624c464576064338cd0d663a038143c1ccdc59e51314ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.5
|