ghandic/jsf

Enums always coerced to strings

Closed this issue · 2 comments

The current enum implementation results in generated int and float data being coerced to str due to how Pydantic handles Union (see these docs). Pydantic will coerce the input to the first type it can match in the Union, which in the current implementation of JSFEnum is always a string for integers and floats.

class JSFEnum(BaseSchema):
    enum: Optional[List[Union[str, int, float, None]]] = []

Pydantic offers the following recommendation to solve this issue:

As such, it is recommended that, when defining Union annotations, the most specific type is included first and followed by less specific types.

However, it also issues a warning concerning Unions inside of List or Dict types:

typing.Union also ignores order when defined, so Union[int, float] == Union[float, int] which can lead to unexpected behaviour when combined with matching based on the Union type order inside other type definitions, such as List and Dict types (because python treats these definitions as singletons). For example, Dict[str, Union[int, float]] == Dict[str, Union[float, int]] with the order based on the first time it was defined. Please note that this can also be affected by third party libraries and their internal type definitions and the import orders.

Because of this I think the best solution is to use Pydantic's Smart Union which will check the entire Union for the best type match before attempting to coerce.

Sounds good, feel free to raise a PR 😃

Thanks for the swift reply! See #26 :)