DataclassTransform - Automagical serialization of custom types

A commonly encountered issue in Dash is the inability to return custom types in callbacks. E.g., if you create a callback that returns a custom type like this,

...

@dataclass
class Person:
    name: str
    date_of_birth: datetime

...

@app.callback(...)
def submit(_, name, date):
    dt = datetime.fromisoformat(date)
    return Person(name, dt) 

You’ll get a serialization error,

dash.exceptions.InvalidCallbackReturnValue: The callback for `<Output `store.data`>`
                returned a value having type `Person`
                which is not JSON serializable.

inspired by a PR from gedemagt, the dash-extensions==1.0.3 release includes a new DataclassTransform which enables serialization of dataclasses automagically. The only modification needed is a type hint for the callback reading the data,

@app.callback(...)
def log(person: Person):
    return f"{person.name} was born on {person.date_of_birth}"  # no (manual) deserialization here

For reference, here is a full example,

from datetime import datetime
from dataclasses import dataclass
from dash_extensions.enrich import DashProxy, Input, html, DataclassTransform, dcc, Output, State

@dataclass
class Person:
    name: str
    date_of_birth: datetime

app = DashProxy(transforms=[DataclassTransform()])
app.layout = html.Div([
    dcc.Input(id="name", value="John Doe"),
    dcc.DatePickerSingle(id="picker", date=datetime(1990, 1, 1)),
    dcc.Store(id="store"),
    html.Button("Submit", id="btn"),
    html.Div(id="log")
])

@app.callback(
    Input("btn", "n_clicks"),
    State("name", "value"),
    State("picker", "date"),
    Output("store", "data")
)
def submit(_, name, date):
    dt = datetime.fromisoformat(date)
    return Person(name, dt)  # no (manual) serialization here

@app.callback(
    Output("log", "children"),
    Input("store", "data"),
)
def log(person: Person):
    return f"{person.name} was born on {person.date_of_birth}" 

if __name__ == "__main__":
    app.run_server()
4 Likes

Perfect topic for a show and tell. Thank you, @Emil .