Skip to content

Instantly share code, notes, and snippets.

@hoshiyosan
Last active November 12, 2021 12:23
Show Gist options
  • Save hoshiyosan/7a23e4c2c6efe14d1d6cfc18c8b9b098 to your computer and use it in GitHub Desktop.
Save hoshiyosan/7a23e4c2c6efe14d1d6cfc18c8b9b098 to your computer and use it in GitHub Desktop.
Dataclass serialization / deserialization in Python
import dataclasses
import importlib
import json
from typing import Any
def dataclass_from_dict(d: dict):
try:
modulepath, classname = d.pop("__class__").rsplit(".", 1)
module = importlib.import_module(modulepath)
Class = getattr(module, classname)
return Class(**d)
except:
return d
class DataclassEncoder(json.encoder.JSONEncoder):
def default(self, o: Any):
if dataclasses.is_dataclass(o):
d = {f.name: getattr(o, f.name) for f in dataclasses.fields(o)}
d["__class__"] = o.__class__.__module__ + "." + o.__class__.__name__
return d
return o
class DataclassDecoder(json.decoder.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(*args, object_hook=dataclass_from_dict, **kwargs)
from dataclasses_utils import
@dataclasses.dataclass
class Contact:
email: str
address: str
@dataclasses.dataclass
class Account:
username: str
contact: str
if __name__ == "__main__":
# create and display an account dataclass
account = Account(
username="toto",
contact=Contact(email="[email protected]", address="123 Main Street, New York, NY 10030"),
)
print(">>>", account)
# compute and display dataclass dump
account_data = json.dumps(account, indent=4, cls=DataclassEncoder)
print(account_data)
# compute and display loaded json, with dataclass automatically deserialized into proper Python object
print(json.loads(account_data, cls=DataclassDecoder))
# This is the output you can expect when running `python main.py`
>>> Account(username='toto', contact=Contact(email='[email protected]', address='123 Main Street, New York, NY 10030'))
>>> {
"username": "toto",
"contact": {
"email": "[email protected]",
"address": "123 Main Street, New York, NY 10030",
"__class__": "__main__.Contact"
},
"__class__": "__main__.Account"
}
>>> Account(username='toto', contact=Contact(email='[email protected]', address='123 Main Street, New York, NY 10030'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment