python-dataclasses-serialization icon indicating copy to clipboard operation
python-dataclasses-serialization copied to clipboard

Add deserializer for Enum

Open kitschen opened this issue 4 years ago • 3 comments

You can add a generic serializer which works for all Enums like so

@JSONSerializer.register_serializer(Enum)
def Enum_serializer(obj: Enum) -> str:
    return obj.name

@JSONSerializer.register_deserializer(Enum)
def Enum_deserializer(cls, name: str) -> Enum:
    try:
        return cls[name]
    except KeyError:
        raise DeserializationError()

Maybe add this to default JSONSerializer or point to it in the docs?

Example test:

from dataclasses import dataclass
from enum import Enum, auto
from typing import Optional
from unittest import TestCase

from dataclasses_serialization.json import JSONSerializer
from dataclasses_serialization.serializer_base import DeserializationError


class Gender(Enum):
    male = auto()
    female = auto()

@dataclass(frozen=True)
class Employee:
    name: Optional[str]
    gender: Optional[Gender]


@JSONSerializer.register_serializer(Enum)
def Enum_serializer(obj: Enum) -> str:
    return obj.name


@JSONSerializer.register_deserializer(Enum)
def Enum_deserializer(cls, name: str) -> Enum:
    try:
        return cls[name]
    except KeyError:
        raise DeserializationError()


class TestEmployee(TestCase):
    def testSerializingNone(self):
        emp = Employee(None, None)
        resDict = JSONSerializer.serialize(emp)

        emp2 = JSONSerializer.deserialize(Employee, resDict)
        self.assertEqual(emp, emp2)


    def testSerializingValue(self):
        emp = Employee("Sarah", Gender.female)
        resDict = JSONSerializer.serialize(emp)

        emp2 = JSONSerializer.deserialize(Employee, resDict)
        self.assertEqual(emp, emp2)

kitschen avatar Apr 22 '20 02:04 kitschen

I'd happily include this as an enum_name_serializer/deserializer utility function (indeed, I have some suspiciously similar code in my personal projects), but I'm against including it by default in JSONSerializer as it's not a canonical serialization.

You could equally well serialize an Enum by its value, or even its index in definition order.

madman-bob avatar Apr 22 '20 15:04 madman-bob

I rewrote this same feature and came to submit a PR only to find @kitschen already suggested it. A supported utility function would be great.

bmc-msft avatar Jun 09 '20 18:06 bmc-msft

Would be nice to have this included by default. I'd vote for serialising the value rather than the name, as it allows you to refactor without breaking existing serialised files.

petered avatar Jan 20 '23 16:01 petered