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

Using TypeDict with djangorestframework_camel_case sets required fields to optional #861

Closed
saschametz opened this issue Nov 16, 2022 · 6 comments
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@saschametz
Copy link

Hi, when using TypeDict in combination with the drf_spectacular.contrib.djangorestframework_camel_case.camelize_serializer_fields hook all fields that are converted from snake_case to camelCase are set to optional.

Serializer:

class RankData(TypedDict):
    value: int
    created_at: str
    name: str
    rank_by_value: bool


class RankSerializer(serializers.Serializer):
    rank_data = serializers.SerializerMethodField()

    def get_rank_data(self) -> RankData:
        return RankData(
            value=290,
            created_at="2022-01-01",
            name="Checkpoint A",
            rank_by_value=False,
        )

Settings:

SPECTACULAR_SETTINGS = {
    "POSTPROCESSING_HOOKS": [
        "drf_spectacular.hooks.postprocess_schema_enums",
        "drf_spectacular.contrib.djangorestframework_camel_case.camelize_serializer_fields",
    ],
}

This produces the following schema:
Screenshot 2022-11-16 at 08 54 12

-> All names that are converted from snake_case to camelCase are set to optional.

Removing "drf_spectacular.contrib.djangorestframework_camel_case.camelize_serializer_fields" from the settings produces the correct schema (all fields are required):
Screenshot 2022-11-16 at 08 56 05

@tfranzel
Copy link
Owner

Looks like the string replacement does not account for nested objects properly. It goes through the nested props properly, but it fails on nested required list.

@tfranzel tfranzel added the bug Something isn't working label Nov 16, 2022
@tfranzel tfranzel added the fix confirmation pending issue has been fixed and confirmation from issue reporter is pending label Nov 16, 2022
@saschametz
Copy link
Author

Thanks for the quick fix @tfranzel
I can confirm it's working now.

@saschametz
Copy link
Author

I just noticed one small issue. After adding a nested child_rank it doesn't convert to camelCase anymore. That's only the case when using List[ChildRankData], but not ChildRankData (without a list).

Serializer:

class ChildRankData(TypedDict):
    value: int
    created_at: str


class RankData(TypedDict):
    value: int
    created_at: str
    name: str
    rank_by_value: bool
    child_rank: List[ChildRankData]


class RankSerializer(serializers.Serializer):
    rank_data = serializers.SerializerMethodField()

    def get_rank_data(self) -> RankData:
        return RankData(
            value=290,
            created_at="2022-01-01",
            name="Checkpoint A",
            rank_by_value=False,
            child_rank=[ChildRankData(value=123, created_at="022-02-02")],
        )

Schema:
Screenshot 2022-11-16 at 17 19 19

@tfranzel
Copy link
Owner

ahh yes, I forgot about that case, since we now do translation manually.

tfranzel added a commit that referenced this issue Nov 17, 2022
Also use feature detection for __required_keys__ instead of
probing Py version
@tfranzel
Copy link
Owner

did a drive-by bugfix that came to my attention. this should work now as expected.

@saschametz
Copy link
Author

Everything works perfectly now 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

2 participants