Problem using json.dump() on datetime type

Hi guys!

I have the following column definition in my model:

...
created_on = db.Column(UTCDateTime, nullable=False, default=now_utc)

In my controller, I eventually call json.dump() on a list that contains created_on values (ex: datetime.datetime(2020, 4, 26, 10, 18, 13, tzinfo=<UTC>)), to return it as JSON serialized back to a DataTable (https://datatables.net/) data source axaj call.

Unfortunately, I get the following Exception:

TypeError: datetime.datetime(2020, 4, 26, 10, 18, 13, tzinfo=<UTC>) is not JSON serializable

Now, I know I could use something like this to “fix” the problem https://code-maven.com/serialize-datetime-object-as-json-in-python, but was wondering if there was a cleaner, Indico-nic way of doing it.

Thanks!

use a marshmallow schema for it. search the codebase for mm.ModelSchema to find examples

I looked around in the code, and found some stuff, but not sure how to use it… :frowning: I guess I’ll do it with How to serialize a datetime object as JSON using Python?

Thanks

Your list is based on a model, right? Let’s assume your model is named Invoice. So you define a schema like this:

class InvoiceSchema(mm.ModelSchema):
    class Meta:
        model = Invoice
        # list everything from your model that you want to include in the JSON data
        fields = ('id', 'created_on', ...)

Then, in your controller where you have a list of Invoice objects, you do this (if you want the RH itself to return the JSON list)

return InvoiceSchema(many=True).jsonify(list_of_invoices)

or if you just want to pass the JSON string to a template, use this got get the JSON string:

invoices_json = InvoiceSchema(many=True).dumps(list_of_invoices)

FWIW, if you use dump instead of dumps you get a Python object that can be jsonified later (e.g. using the |tojson filter in a Jinja template).


Using Marshmallow schemas like this is the way to go for any object that should be converted to JSON, since it ensures you have a well-defined structure for it.

However, if your code is currently as simple as creating some dicts that are eventually jsonified, you can also simply call .isoformat() on the datetime object to get a string.