marshmallow_dataclass icon indicating copy to clipboard operation
marshmallow_dataclass copied to clipboard

Add example of enum usage to documentation

Open mcsheehan opened this issue 4 years ago • 16 comments
trafficstars

It is specified in the documentation to use pip3 install "marshmallow-dataclass[enum,union]"

However whenever an enum field is used with the dataclass I'm getting a ['Enum name must be string'] error. I have tried several different ways of writing my enum class, and whilst I'm sure I'll get there it isn't immediately obvious how to use the enum feature with dataclasses.

A couple of lines in a readme file would fix this and be greatly appreciated.

mcsheehan avatar Dec 15 '20 10:12 mcsheehan

Hello, Can you include the failing code sample triggering the Enum name must be string error ?

lovasoa avatar Dec 16 '20 11:12 lovasoa

Hello - it's less a code issue and more a lack of an example in the documentation issue. Took me a while to work out how to add the enum field to the dataclass. Really nice work on the library.

I've got to the bottom of it - want me to start a pull request with documentation changes?

Essentially it's the following:

class TrafficLight(Enum):
    RED = "RED"
    GREEN = "GREEN"
    BLUE = "BLUE"

@dataclass()
class MyLovelyMarshmallowDataclass:
    id: str
    status: str = EnumField(TrafficLight)

mcsheehan avatar Dec 16 '20 11:12 mcsheehan

I've got to the bottom of it - want me to start a pull request with documentation changes?

If you can, that would be great !

The canonical way to do it should be

class TrafficLight(Enum):
    RED = "RED"
    GREEN = "GREEN"
    BLUE = "BLUE"

@dataclass()
class MyLovelyMarshmallowDataclass:
    id: str
    status: TrafficLight

lovasoa avatar Dec 16 '20 13:12 lovasoa

I had the same issue today, my enum was in the format:

class TrafficLight(Enum):
    RED = "red",  "RED"
    GREEN = "green", "GREEN"
    BLUE = "blue", "BLUE"

I had to use the following

@dataclass()
class MyLovelyMarshmallowDataclass:
    id: str
    status: set

Any workaround to be able to use directly status: TrafficLight instead of status: set (I don't need a default)? Seems that when it gets by name, EnumField tries to check if it's a string and it fails otherwise.

bogdangoie avatar Jan 04 '21 19:01 bogdangoie

Yes, it does need to be a string ? If what you want is a set if TrafficLights, then just give it the type Set[TrafficLights].

lovasoa avatar Jan 05 '21 09:01 lovasoa

Yes, it does need to be a string ? If what you want is a set if TrafficLights, then just give it the type Set[TrafficLights].

Unfortunately that doesn't work, it throws TypeError: typing.Set[TrafficLight] is not a dataclass and cannot be turned into one.

bogdangoie avatar Jan 05 '21 09:01 bogdangoie

Yes, sorry, we don't support set, you'll have to use List.

lovasoa avatar Jan 05 '21 11:01 lovasoa

How do I mention a default value for a dataclass field when using EnumField?

demberto avatar Feb 10 '21 12:02 demberto

This has always worked for me:

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

@dataclass
class Thing:
    color: Color = Color.RED

mivade avatar Feb 10 '21 15:02 mivade

This has always worked for me:

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

@dataclass
class Thing:
    color: Color = Color.RED

Just an important observation: if you follow this approach, the schema.load() will expect by default the field for "color" to be a string. Example:

schema = Thing.Schema()
schema.load({ "color": Color.RED })  # this will throw a ValidationError
schema.load({ "color": Color.RED.name })  # this will work.

If you want schema.load({ "color": Color.RED }) to work, you need to pass the option "by_value": True as such:

@dataclass
class Thing:
    color: Color = field(default=Color.RED, metadata={"by_value": True})

I think this should be mentioned in the documentation because it seems that the default behavior differs from the one in mashmallow-enum, at least according to their README.

rscmendes avatar Mar 04 '21 22:03 rscmendes

The default behavior of mashmallow-enum is by_value=False. Its readme is not specifying this behavior.

We have many Enums and in our case they should be serialized by value. This means that we have to add metadata={"by_value": True} to each field. It would be great if one could set this parameter for all Enums or to specify a different Enum class for the whole schema generation process.

jan-23 avatar Apr 26 '21 16:04 jan-23

If I run

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

@dataclass
class Thing:
    color: Color = Color.RED

the field doesn't appear on swagger UI, but

The less canonical version

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

@dataclass
class Thing:
    color: str= Color.RED.value

works correctly.

Do you know if this is the expected behavior or there's an outstanding missing support in swagger-ui for enums?

FreCap avatar Apr 26 '21 19:04 FreCap

We have many Enums and in our case they should be serialized by value. This means that we have to add metadata={"by_value": True} to each field. It would be great if one could set this parameter for all Enums or to specify a different Enum class for the whole schema generation process.

You can use NewType, or a custom base Schema

lovasoa avatar Apr 27 '21 17:04 lovasoa

Is there any workaround related to this when using pure python dataclasses?

gbrennon avatar May 24 '21 06:05 gbrennon

We have many Enums and in our case they should be serialized by value. This means that we have to add metadata={"by_value": True} to each field. It would be great if one could set this parameter for all Enums or to specify a different Enum class for the whole schema generation process.

You can use NewType, or a custom base Schema

Would it be possible to have a sample of a working code that uses enum specifically as a reference? Also, somewhat related to the whole enum theme. I ran into issues trying to define a dataclass with a property that is a List of enums. I don't seem to be able to figure out how to pass metadata to the list element constructor.

seva0stapenko avatar Jun 23 '21 18:06 seva0stapenko

How to perform similar to above for a list of colors, e.g.:

@dataclass
class Thing:
    color: list[Color] = field(default=Color.RED, metadata={"by_value": True})

https://github.com/lovasoa/marshmallow_dataclass/issues/255

rayrapetyan avatar Jan 20 '24 21:01 rayrapetyan