Skip to content

Instantly share code, notes, and snippets.

@gatopeich
Created February 19, 2019 15:08
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save gatopeich/1efd3e1e4269e1e98fae9983bb914f22 to your computer and use it in GitHub Desktop.
Save gatopeich/1efd3e1e4269e1e98fae9983bb914f22 to your computer and use it in GitHub Desktop.
Python 3.7 dataclass to/from dict/json
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
@nflatrea
Copy link

Using annotations you remove all inherited fields

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment