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

Custom serializer discarded when WrapSerializer is used #9460

Open
1 task done
ornariece opened this issue May 20, 2024 · 4 comments
Open
1 task done

Custom serializer discarded when WrapSerializer is used #9460

ornariece opened this issue May 20, 2024 · 4 comments
Labels
bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation

Comments

@ornariece
Copy link
Contributor

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

The use of Annotated combined with a WrapSerializer prevents a custom serializer from being used.
The following example code should be self-explanatory:

Example Code

from typing import Annotated

import pydantic
import pydantic_core.core_schema


class MyCustomType:
    def __init__(self, val: int):
        self.val: int = val

    def __repr__(self):
        return 'my_custom_type_repr'

    @classmethod
    def __get_pydantic_core_schema__(cls, _source, _handler):
        return pydantic_core.core_schema.no_info_plain_validator_function(
            cls,
            serialization=pydantic_core.core_schema.plain_serializer_function_ser_schema(
                lambda _v: 'custom_serialization'
            ),
        )


class MyModel(pydantic.BaseModel):
    x: MyCustomType


class MyModelUsingAnnotated(pydantic.BaseModel):
    x: Annotated[MyCustomType, pydantic.WrapSerializer(lambda v, h: f'wrapped:{h(v)}')]


if __name__ == '__main__':
    my_model = MyModel(x=1)
    print(my_model.model_dump())
    # result: {'x': 'custom_serialization'}
    # expected: {'x': 'custom_serialization'}

    my_model_using_annotated = MyModelUsingAnnotated(x=1)
    print(my_model_using_annotated.model_dump())
    # result: {'x': "wrapped:my_custom_type_repr"}
    # expected: {'x': 'wrapped:custom_serialization'}

Python, Pydantic & OS Version

pydantic version: 2.7.1
        pydantic-core version: 2.18.2
          pydantic-core build: profile=release pgo=true
                 install path: -
               python version: 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)]
                     platform: Windows-10-10.0.19045-SP0
             related packages: mypy-1.2.0+dev.456dcbdd6a2f9b36249e0e7d31e521f5678a8235 typing_extensions-4.11.0
                       commit: unknown
@ornariece ornariece added bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation labels May 20, 2024
@sydney-runkle
Copy link
Member

@ornariece,

Hmm, thanks for reporting this. I don't think this is necessarily a bug, but perhaps a change request. Looks like the current behavior is such that the custom get schema function overrides any changes applied via annotations.

@adriangb, is this intentional? Is this something we want to change?

@adriangb
Copy link
Member

At first glance I don't think it's a bug per se but maybe more like a limitation of what you can achieve with these annotations.

@ornariece
Copy link
Contributor Author

ornariece commented May 29, 2024

Looks like the current behavior is such that the custom get schema function overrides any changes applied via annotations.

you got that backwards: the annotation is overriding the custom serializer of the type.

From an implementation point-of-view, I get why you'd think this is more a limitation than a bug, since the workaround for a user is pretty straightforward. However, I'd definitely argue that this is conceptually a bug. Also, it can be very disorientating for a user using a custom type from a 3rd-party library: here the user would likely not be aware beforehand that the custom type is using a custom serializer method, and would annotate it all the same in their code, at which point they would be confused as to why their WrapSerializer doesn't actually wrap the expected serialization.

@sydney-runkle
Copy link
Member

you got that backwards: the annotation is overriding the custom serializer of the type.

Ah yes, you're right. This seems like a bug!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation
Projects
None yet
Development

No branches or pull requests

3 participants