Reputation: 631
If I write
import json
class Color():
FUSCHIA = 0x00
TURQUOISE = 0x01
EMERALD = 0x02
def my_default_serializer(o):
return o.__dict__
def get_colors():
return json.dumps(
{
'dark_bg': True,
'colors_batch': [Color.TURQUOISE,
Color.EMERALD]
},
default=my_default_serializer
)
print(get_colors())
then I get, as expected:
{"dark_bg": true, "colors_batch": [1, 2]}
Now suppose I modernize this code by introducing enum.Enum
. Among other things, this is handy because Enum
will parse a string (read from a file, for example), and hence I replace the code above with:
import json
from enum import Enum
class Color(Enum):
FUSCHIA = 0x00
TURQUOISE = 0x01
EMERALD = 0x02
def my_default_serializer(o):
return o.__dict__
def get_colors():
return json.dumps(
{
'dark_bg': True,
'colors_batch': [Color['TURQUOISE'],
Color['EMERALD']]
},
default=my_default_serializer
)
print(get_colors())
This introduces the error:
AttributeError: 'mappingproxy' object has no attribute '__dict__'
(and if I don't specify the default serializer, I get TypeError: Object of type 'Color' is not JSON serializable
).
How should I JSON-serialize Enum-children?
Upvotes: 2
Views: 721
Reputation: 23815
see below - seems to work. The idea is to override default
method of JSONEncoder
, check if the incoming argument is an instance of a Color
and handle it.
import json
from enum import Enum
class Color(Enum):
FUSCHIA = 0x00
TURQUOISE = 0x01
EMERALD = 0x02
class EnumEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Enum):
return {"__enum__": str(obj)}
return json.JSONEncoder.default(self, obj)
def get_colors():
return json.dumps(
{
'dark_bg': True,
'colors_batch': [Color['TURQUOISE'],
Color['EMERALD']]
}, cls=EnumEncoder
)
print(get_colors())
Upvotes: 3