Pydantic: Question: serializing a list of objects

Created on 18 Jul 2019  路  2Comments  路  Source: samuelcolvin/pydantic

Question

For bugs/questions:

  • OS: Ubuntu 19.04
  • Python version 3.7.3
  • Pydantic version 0.30.1

Hi, based on one of your examples let's say I have this

from datetime import datetime
from typing import List
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: datetime = None
    friends: List[int] = []

The thing is I want to be to serialize a list of users, like this one:

users_list = [
    {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']},
    {'id': '456', 'signup_ts': '2017-06-02 12:22', 'friends': ['you']},
]

But the only way I found to be able to do it, was by creating a second class to nest User as a list inside,

class UserList(BaseModel):
    users: List[User]

But I don't want my response nested inside a users key, I want my response just to be the list, so I can paginate it, etc. Normally, using drf this can be achieved by setting many=True when instantiating the serializer:

serializer = UserSerializer(data=users_list, many=True)
users = serializer.data

Is there a pydantic way to achieve this like I would with drf?

(Of course, this is a simple example, the real scenario will be to use Django ORM to query all objects and serialize them, but for simplicity I will stick to a simpler example)

Most helpful comment

The "right" way to do this in pydantic is to make use of "Custom Root Types". You still need to make use of a container model:

class UserList(BaseModel):
    __root__: List[User]

but then the following will work:

UserList.parse_obj([
    {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']},
    {'id': '456', 'signup_ts': '2017-06-02 12:22', 'friends': ['you']},
])

(and will put the values inside the __root__ property).

Unfortunately, I think there is not good serialization support for this yet, so I think when you go to return the results, if you want to return just a list you'll still need to return UserList.__root__.

I don't think there is currently a unified interface that gets you a serialized/unstructured version of the model that respects the __root_model__, but if this is what you are looking for, it could be worth building.

All 2 comments

The "right" way to do this in pydantic is to make use of "Custom Root Types". You still need to make use of a container model:

class UserList(BaseModel):
    __root__: List[User]

but then the following will work:

UserList.parse_obj([
    {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']},
    {'id': '456', 'signup_ts': '2017-06-02 12:22', 'friends': ['you']},
])

(and will put the values inside the __root__ property).

Unfortunately, I think there is not good serialization support for this yet, so I think when you go to return the results, if you want to return just a list you'll still need to return UserList.__root__.

I don't think there is currently a unified interface that gets you a serialized/unstructured version of the model that respects the __root_model__, but if this is what you are looking for, it could be worth building.

Thank you @dmontagu !

So based on what you suggested, I ended up with this:

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = MyModelList.parse_obj(page)
            return self.get_paginated_response(dict(serializer)['__root__'])

        serializer = MyModelList.parse_obj(list(queryset.values()))
        return Response(dict(serializer)['__root__'])

This actually works well with Django + DRF using a ListCreateAPIView class-based view and it returns a proper paginated response from a Django QuerySet.

Maybe this isn't an optimal way to integrate it with DRF, but still is a working proof of concept.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MrMrRobat picture MrMrRobat  路  22Comments

cazgp picture cazgp  路  34Comments

jasonkuhrt picture jasonkuhrt  路  19Comments

koxudaxi picture koxudaxi  路  25Comments

Yolley picture Yolley  路  18Comments