-
-
Save liquidgenius/95be15cd55a59fc2fc8a344eea610ddc to your computer and use it in GitHub Desktop.
Python 3.7 dataclass to/from dict/json
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
from dataclasses import dataclass, fields as datafields | |
from ujson import dumps, loads | |
# Note: ujson seamlessly serializes dataclasses, unlike stdlib's json | |
@dataclass | |
class Point: | |
x: float | |
y: float | |
# Shallow dataclass can be rebuilt from dict/json: | |
point = Point(1,2) | |
assert point == Point(**loads(dumps(point))) | |
# However, deep dataclass's fields won't be rebuilt from the json dict: | |
@dataclass | |
class Line: | |
a: Point | |
b: Point | |
line = Line(Point(1,2), Point(3,4)) | |
assert line != Line(**loads(dumps(line))) | |
print(line, '\n !=', Line(**loads(dumps(line)))) | |
# Line(a=Point(x=1, y=2), b=Point(x=3, y=4)) | |
# != Line(a={'x': 1, 'y': 2}, b={'x': 3, 'y': 4}) | |
# But we can simply reconstruct recursively: | |
def dataclass_from_dict(klass, dikt): | |
try: | |
fieldtypes = {f.name:f.type for f in datafields(klass)} | |
return klass(**{f:dataclass_from_dict(fieldtypes[f],dikt[f]) for f in dikt}) | |
except: | |
return dikt | |
line_from_dict = dataclass_from_dict(Line,loads(dumps(line))) | |
assert line == line_from_dict |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment