Issue
Say you've got multiple encoders, like this:
class JsonDataClassEncoder(json.JSONEncoder):
"""
Supports dataclasses
"""
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
return super().default(o)
class JsonEnumEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Enum):
return obj.name
return super().default(obj)
Is there a way to combine them, without subclassing them, such that it would be possible to use
json.dumps(opj, cls=MultipleJsonEncoders(JsonEnumEncoder, JsonDataClassEncoder))
Solution
class MultipleJsonEncoders():
"""
Combine multiple JSON encoders
"""
def __init__(self, *encoders):
self.encoders = encoders
self.args = ()
self.kwargs = {}
def default(self, obj):
for encoder in self.encoders:
try:
return encoder(*self.args, **self.kwargs).default(obj)
except TypeError:
pass
raise TypeError(f'Object of type {obj.__class__.__name__} is not JSON serializable')
def __call__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
enc = json.JSONEncoder(*args, **kwargs)
enc.default = self.default
return enc
Usage
import json
import enum
import datetime
class JsonDateEncoder(json.JSONEncoder):
"""JSON serializer for objects not serializable by default json code"""
def default(self, o):
if isinstance(o, (datetime.datetime, datetime.date)):
return o.isoformat()
return super().default(o)
class JsonEnumEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, Enum):
return o.name
return super().default(o)
class Enumm(enum.Enum):
X = enum.auto()
obj = {'time': datetime.datetime.now(), 'enum': Enumm.X}
encoder = MultipleJsonEncoders(JsonDateEncoder, JsonEnumEncoder)
In [502]: json.dumps(obj, cls=encoder)
Out[502]: '{"time": "2020-12-23T08:51:43.646022", "enum": "X"}'
Answered By - tsorn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.