Skip to content
New issue

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

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

Already on GitHub? # 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 👍

# for free to join this conversation on GitHub. Already have an account? # 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