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

Unable to get custom json serialization for enums to work #1986

Closed
viveksunder opened this issue Aug 28, 2020 · 3 comments
Closed

Unable to get custom json serialization for enums to work #1986

viveksunder opened this issue Aug 28, 2020 · 3 comments
Labels
answered bug Something isn't working reviewed

Comments

@viveksunder
Copy link
Contributor

Hi there! We are using pydantic to define our API models and have a use-case where certain fields stored in our database (mongodb) are enums and need to be translated into an API/user friendly representation. We tried the following in order to solve this problem -

  • Define a common enum base class
  • Define a common pydantic model base class
  • Define a class Config section in the above pydantic base class that will implement serialization for our enums.
import enum


import pydantic
from fastapi.encoders import jsonable_encoder


class BaseEnum(enum.Enum):
    """
    A base class for all enums that require custom serialization.
    """

    def get_api_repr(self):
        """
        All inheriting classes must implement `def get_api_repr`
        """
        raise NotImplementedError


class SomeStatusEnum(BaseEnum):
    ACTIVE = "ACTIVE"
    INACTIVE = "INACTIVE"

    def get_api_repr(self):
        """
        Return an API friendly value.
        """
        if self.value == self.ACTIVE.value:
            return "Active"

        return "Inactive"


class AppBaseModel(pydantic.BaseModel):
    """
    All app models should inherit from this base class
    so they can benefit from common configuration.
    """

    class Config:
        json_encoders = {
            BaseEnum: lambda v: v.get_api_repr(),
        }


class CustomModel(AppBaseModel):
    """ This does something custom ;) """

    status: SomeStatusEnum


example = CustomModel(status=SomeStatusEnum.ACTIVE)
print(jsonable_encoder(example))

Output -

{'status': 'ACTIVE'}

Would expect -

{'status': 'Active'}

Environment

  • OS: Linux
  • Python version: 3.8.5
  • FastAPI Version: 0.61.0
  • Pydantic Version: 1.6.1

PS - We only recently started using FastAPI at work and we love it!!

@viveksunder viveksunder added the question Question or problem label Aug 28, 2020
@viveksunder
Copy link
Contributor Author

Also FYI - I've identified that in

if isinstance(obj, Enum):
because for enums this returns .value instead of first checking if there is a custom encoder defined for that type that this explains why the custom encoder I added in the example above doesn't get picked up.

Does it make more sense to check if any custom encoders for the type have been defined first before applying the default for the type? If so, I'm happy to look into contributing a PR to explore that - just wanted to check if my thinking is reasonable first.

@tiangolo tiangolo changed the title Unable to get custom json serialization for enums to work 🐛 Prefer custom encoder over defaults if specified in jsonable_encoder Jan 23, 2022
@tiangolo tiangolo changed the title 🐛 Prefer custom encoder over defaults if specified in jsonable_encoder Unable to get custom json serialization for enums to work Jan 23, 2022
@tiangolo tiangolo added bug Something isn't working and removed question Question or problem labels Jan 23, 2022
@tiangolo
Copy link
Owner

Thanks for the report and for the fix in the PR @viveksunder! 🚀

This is now available in FastAPI 0.73.0, released in a couple of hours. 🎉

@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2022

Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs.

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

No branches or pull requests

2 participants