oxan / djangorestframework-dataclasses

Dataclasses serializer for Django REST framework
BSD 3-Clause "New" or "Revised" License
431 stars 28 forks source link

DataclassListSerializer can't deserialize objects #75

Closed erickguan closed 1 year ago

erickguan commented 1 year ago

Hello, I am working on deserializing Jira user lists. The gist of the code looks like this:

from dataclasses import dataclass

from rest_framework_dataclasses.serializers import DataclassSerializer

from integrations.jira.serializers.common import UserBasic

@dataclass
class User:
    displayName: str

class UserSerializer(DataclassSerializer):
    class Meta:
        dataclass = User

serializer = UserSerializer(data=[{"displayName": "a"}], many=True)
serializer.is_valid()
users = serializer.save()

The last save raises.

Traceback (most recent call last):
  File "/opt/src/integrations/tests/test_jira_serializers_inbound.py", line 19, in test_UserSerializer_deserialize
    users = serializer.save()
            ^^^^^^^^^^^^^^^^^
  File "/opt/virtualenv/lib/python3.11/site-packages/rest_framework/serializers.py", line 698, in save
    validated_data = [
                     ^
  File "/opt/virtualenv/lib/python3.11/site-packages/rest_framework/serializers.py", line 699, in <listcomp>
    {**attrs, **kwargs} for attrs in self.validated_data
    ^^^^^^^^^^^^^^^^^^^
TypeError: 'User' object is not a mapping

attrs in the Django Rest Framework is a dataclass so it is not possible to unwrap it.

The dependency versions: django==3.2.12 djangorestframework==3.12.4 djangorestframework-dataclasses==1.2.0

How can I help?

oxan commented 1 year ago

That indeed looks a like bug, but I'll have to think a bit about how this can best be fixed. Having validated_data be a dataclass instance instead of a dict isn't something DRF likes.

For now you can workaround it by accessing validated_data instead of calling save():

users = serializer.validated_data
erickguan commented 1 year ago

Okay, thanks. I can confirm the workaround (validated_data) works well.