Skip to content

Instantly share code, notes, and snippets.

@matteobertozzi
Last active June 2, 2024 12:27
Show Gist options
  • Save matteobertozzi/09089f8eb33b985edb18afe558d3c26e to your computer and use it in GitHub Desktop.
Save matteobertozzi/09089f8eb33b985edb18afe558d3c26e to your computer and use it in GitHub Desktop.
Python dataclass from dict
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