diff --git a/src/marshmallow/fields.py b/src/marshmallow/fields.py index e6c7366df..841043172 100644 --- a/src/marshmallow/fields.py +++ b/src/marshmallow/fields.py @@ -1928,6 +1928,7 @@ class Enum(Field[_EnumT]): If `by_value` is `False` (default), enum members are (de)serialized by symbol (name). If it is `True`, they are (de)serialized by value using `marshmallow.fields.Raw`. If it is a field instance or class, they are (de)serialized by value using this field. + If `by_value` is enabled on an enum with a `None` value, `allow_none` defaults to `True`. .. versionadded:: 3.18.0 """ @@ -1968,6 +1969,8 @@ def __init__( self.choices_text = ", ".join( str(self.field._serialize(m.value, None, None)) for m in enum ) + if "allow_none" not in kwargs and any(m.value is None for m in enum): + self.allow_none = True def _serialize( self, value: _EnumT | None, attr: str | None, obj: typing.Any, **kwargs diff --git a/tests/base.py b/tests/base.py index 07d3cc85b..91c7875ac 100644 --- a/tests/base.py +++ b/tests/base.py @@ -28,6 +28,11 @@ class HairColorEnum(Enum): red = "red hair" +class UltimatumEnum(Enum): + all = float("inf") + nothing = None + + class DateEnum(Enum): date_1 = dt.date(2004, 2, 29) date_2 = dt.date(2008, 2, 29) @@ -57,6 +62,7 @@ class DateEnum(Enum): functools.partial(fields.Enum, GenderEnum), functools.partial(fields.Enum, HairColorEnum, by_value=fields.String), functools.partial(fields.Enum, GenderEnum, by_value=fields.Integer), + functools.partial(fields.Enum, UltimatumEnum, allow_none=False), ] diff --git a/tests/test_deserialization.py b/tests/test_deserialization.py index 2f449a4ed..eb7faa9ad 100644 --- a/tests/test_deserialization.py +++ b/tests/test_deserialization.py @@ -24,6 +24,7 @@ DateEnum, GenderEnum, HairColorEnum, + UltimatumEnum, assert_date_equal, assert_time_equal, central, @@ -1281,6 +1282,10 @@ def test_enum_field_by_value_field_wrong_type(self): with pytest.raises(ValidationError, match="Not a valid date."): field.deserialize("30/02/2004") + def test_enum_by_value_allow_none_default(self): + field = fields.Enum(UltimatumEnum, by_value=True) + assert field.deserialize(None) is None + def test_deserialization_function_must_be_callable(self): with pytest.raises(TypeError): fields.Function(lambda x: None, deserialize="notvalid")