Created
February 15, 2022 15:54
-
-
Save laundmo/3bb574545f47ed274fc83bdcc07e2c59 to your computer and use it in GitHub Desktop.
very basic roundtrip dataclass to json-serializeable dict using converters per exact type
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# I often find myself wanting a easy way to define custom converters for | |
# converting dataclasses to and from dicts, but don't want to import | |
# another dependency (dataclass_factory). In this example i'm converting datetimes. | |
# published as MIT license: https://opensource.org/licenses/MIT | |
from dataclasses import dataclass, fields | |
from datetime import datetime | |
from typing import List | |
def strs_to_dts(strs: List[str]) -> List[datetime]: | |
return list(map(datetime.fromisoformat, strs)) | |
def dts_to_strs(dts: List[datetime]) -> List[str]: | |
return list(map(datetime.isoformat, dts)) | |
# types not listed in the converters will have the value passed into the type for both conversions: int(value) | |
converters = { | |
List[datetime]: (strs_to_dts, dts_to_strs), | |
datetime: (datetime.fromisoformat, datetime.isoformat), | |
} | |
@dataclass | |
class Test: | |
a: List[datetime] | |
b: int | |
c: datetime | |
def as_dict(self): | |
result = {} | |
for item in fields(self): | |
from_dict, to_dict = converters.get(item.type, (item.type, item.type)) | |
result[item.name] = to_dict(getattr(self, item.name)) | |
return result | |
@classmethod | |
def from_dict(cls, data): | |
kwargs = {} | |
for item in fields(cls): | |
from_dict, to_dict = converters.get(item.type, (item.type, item.type)) | |
kwargs[item.name] = from_dict(data[item.name]) | |
return cls(**kwargs) | |
m1 = Test(a=[datetime.now(), datetime.now()], b=1, c=datetime.now()) | |
print(m1.as_dict()) # {'a': ['2022-02-15T16:36:13.744117', '2022-02-15T16:36:13.744117'], 'b': 1, 'c': '2022-02-15T16:36:13.744117'} | |
print(m1 == Test.from_dict(m1.as_dict())) # True | |
print(Test.from_dict(m1.as_dict())) # Test(a=[datetime.datetime(2022, 2, 15, 16, 36, 13, 744117), datetime.datetime(2022, 2, 15, 16, 36, 13, 744117)], b=1, c=datetime.datetime(2022, 2, 15, 16, 36, 13, 744117)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment