Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"UUID is not JSON serializable" when generating a schema for a choice field with UUID options. #1079

Closed
phb-teleclinic opened this issue Sep 20, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@phb-teleclinic
Copy link
Contributor

phb-teleclinic commented Sep 20, 2023

Describe the bug
drf-spectacular crashes when generating a schema for a choice field with UUID options.

To Reproduce

Using drf-spectacular 0.26.4.

Create and API with the following serializer:

import uuid
from rest_framework import serializers

class TestSerializer(serializers.Serializer):
    foo_field = serializers.ChoiceField(
        allow_null=True,
        choices=[
            (uuid.UUID('44ec224e-0d22-48f0-07e2-2fc996160e25'), 'foo'),
            (uuid.UUID('cffceb17-8c0z-434e-9aba-de5f5126d558'), 'bar')
        ]
    )

generating the schema for the API triggers:

    schema = generator.get_schema(request=None, public=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    result = hook(result=result, generator=self, request=request, public=public)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/test-venv/lib/python3.11/site-packages/drf_spectacular/hooks.py", line 116, in postprocess_schema_enums
    prop_hash = list_hash(prop_schema['enum'])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/test-venv/lib/python3.11/site-packages/drf_spectacular/plumbing.py", line 837, in list_hash
    return hashlib.sha256(json.dumps(list(lst), sort_keys=True).encode()).hexdigest()
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    **kw).encode(obj)
          ^^^^^^^^^^^
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type UUID is not JSON serializable

Expected behavior
Expected the schema generation to succeed.

Possible fix
Change list_hash to use a JSON encoder that supports UUIDs like DjangoJSONEncoder.

@tfranzel
Copy link
Owner

Hi @phb-teleclinic,

interesing usage of the choices parameter. I think people usually just drop in the UUID string in that case, but your solution is indeed a bit more robust. I think it is a good idea to employ the same serialization as the framework does.

@tfranzel tfranzel added the bug Something isn't working label Sep 20, 2023
phb-teleclinic added a commit to phb-teleclinic/drf-spectacular that referenced this issue Sep 21, 2023
…choices.

The crash was fixed by replacing the JSON encoder used to hash elements
for enum deduplication with DRF JSON encoder which is capable of handling
type outside of the usual JSON standard types.
tfranzel added a commit that referenced this issue Sep 21, 2023
Fix (#1079) crash when generating schema for field with UUID choices.
@tfranzel
Copy link
Owner

Excellent! Thanks @phb-teleclinic for the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants