Last active
June 2, 2024 12:27
-
-
Save matteobertozzi/09089f8eb33b985edb18afe558d3c26e to your computer and use it in GitHub Desktop.
Python dataclass from dict
This file contains hidden or 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
from dataclasses import dataclass, is_dataclass, asdict as dataclass_as_dict, fields as dataclass_fields | |
def dataclass_from_dict(cls, src): | |
kwargs = {} | |
fields_lookup = {field.name: field for field in dataclass_fields(cls)} | |
for field_name, value in src.items(): | |
field = fields_lookup.get(field_name) | |
if not field: | |
#logger.warning('config field %s not found for class %s', field_name, cls.__name__) | |
continue | |
if field.init: | |
if is_dataclass(field.type): | |
kwargs[field_name] = dataclass_from_dict(field.type, value) | |
elif isinstance(value, list): | |
data_type = field.type | |
list_cls = data_type.__args__[0] | |
if is_dataclass(list_cls): | |
kwargs[field_name] = [dataclass_from_dict(list_cls, v) for v in value] | |
else: | |
kwargs[field_name] = value | |
elif isinstance(value, dict): | |
data_type = field.type | |
#key_cls = data_type.__args__[0] | |
val_cls = data_type.__args__[1] | |
if is_dataclass(val_cls): | |
kwargs[field_name] = {k: dataclass_from_dict(val_cls, v) for k, v in value.items()} | |
else: | |
kwargs[field_name] = value | |
else: | |
kwargs[field_name] = value | |
return cls(**kwargs) | |
if __name__ == '__main__': | |
@dataclass | |
class Bar: | |
x: int | |
@dataclass | |
class Foo: | |
a: int | |
b: str | |
c: list[Bar] | |
d: dict[str, Bar] | |
foo = Foo(10, 'bbbb', [Bar(12), Bar(13)], {'a': Bar(14), 'b': Bar(15)}) | |
foo_dict = dataclass_as_dict(foo) | |
print(foo) | |
print(foo_dict) | |
print(dataclass_from_dict(Foo, foo_dict)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment