I achieved the desired behavior by extending Flask's DefaultJSONProvider. But as the majority of the information that I found online was outdated, here is how I did it.
- A custom provider extending DefaultJSONProvider. It checks if the object to serialize is one of the relevant FireO classes and converts them into a dictionary or array of dictionaries. For anything else, it defaults back to DefaultJSONProvider behaviour.
from fireo.models import Model
from fireo.queries.query_iterator import QueryIterator
from flask.json.provider import DefaultJSONProvider
class CustomJsonProvider(DefaultJSONProvider):
def dumps(self, obj, **kw):
"""
Define how to serialize objects that aren't natively serializable by json.dumps.
Returns:
- A dictionary if the object is a FireO model
- A list of dictionaries if the object is a FireO QueryIterator or list of models
- Datetime objects are serialized to iso strings
- All other clases are delegated back to DefaultJSONProvider
"""
if isinstance(obj, Model):
obj = obj.to_dict()
self.datetime_to_string(obj)
elif (isinstance(obj, QueryIterator)
or (isinstance(obj, list) and all(isinstance(item, Model) for item in obj))):
obj = [item.to_dict() for item in obj]
# all datetimes to strings
for item in obj:
self.datetime_to_string(item)
return super().dumps(obj, **kw) # Delegate to the default dumps
def datetime_to_string(self, obj):
# Convert all datetimes in the dictionary to string
for key, value in obj.items():
if isinstance(value, datetime):
obj[key] = value.isoformat()
- Pass this CustomJsonProvider to Flask's app:
app = Flask(__name__)
app.json_provider_class = CustomJsonProvider
app.json = CustomJsonProvider(app)
P.S: I was hoping to extend FireO's Model classes, but I'm having some difficulties understanding the inner workings of Flask's jsonify and dumps, especially what they require for class serialization.Any advice here would be great.