Custom default function for jsonify #220

dag opened this Issue Apr 19, 2011 · 10 comments


None yet

8 participants


It would be neat to be able to control the serialization of arbitrary objects with jsonify. The dumps function allows you to pass a callable for this. I propose the addition of either an overridable method on the Flask class that is passed by jsonify, or a decorator for registering such a function. The "default default" could simply raise TypeError, the "default default" for the json module.

class JSONAdaptiveFlask(Flask):

    def json_defaults(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
            return obj.__json__()
        except AttributeError:
            raise TypeError

… or …

def json_adaption(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
        return obj.__json__()
    except AttributeError:
        raise TypeError

Unlike the rejected pull-request, this should be thread-safe. As for direct use of the json module, one can simply pass the reference:

json.dumps(obj, default=app.json_defaults)

In a discussion on IRC, Armin expressed concern that this kind of adaption isn't very useful in practice, because it differs between requests what one wants serialized from an object. This problem can be solved by exploiting the fact that jsonify is request-bound, and the defaults function is able to read context-locals such as 'g'. It may not "feel" right but it is essentially what we need: a global state for the request.

class User(Model):

    def __json__(self):
        data = dict(, joined=self.created_at)
        if g.user is self:
        if g.verbose_json:

The gain is that we can simplify views and structure the code better by moving model-logic to models. We can avoid repeating ourselves — the serialization is recursive, we just reference a datetime object and a list of instances of the Post model. We don't lose anything because by default it will behave as before and regardless we can still pass standard types directly to jsonify.

If you [Armin] approve the idea and decide on an API, I'll try my hand at a patch if you like.


There might be a better name for 'json_defaults' BTW. Suggestions?


In the standard lib, it's called 'cls', which is not terribly descriptive. . Maybe 'json_cls', or 'json_dumper'? Those are both quite hideous as well though.

"To use a custom JSONEncoder subclass (e.g. one that overrides the default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used."


+1 on this issue. datetime objects in particular don't serialize by default, which makes writing JSON API's with jsonify difficult, as this is a common data type in API's.

+1 to dag 's comment, as a simple answer we would only need to be able to pass a callable to the internal json.dumps call in the 'default' kwarg.

Unfortunately, the way jsonify is currently written, the args, *kwargs arguments to jsonify makes it impossible to specify any arguments to the internal json.dumps 'out of band' from your data. I'm not sure how to implement a way to pass in 'default', while at the same time keeping backwards compatibility and allowing 'default' as a key in your data. Perhaps a new json helper, or json oriented extension is needed?


I see a few of options here.

  1. Change jsonify to use an explicit JSONEncoder object that is provided by the Flask class. There would be a way for people to replace the default JSONEncoder object with their own. This would allow encoding customization such as providing a default callback function.
  2. Instead of owning the JSONEncoder object, the Flask class could just own a default callback function that could be replaced by users. It always be passed to jsonify and would default to None.
  3. Provide a more advanced JSON encoder registration system as hinted at above. @app.json_encoder(DateTime) could register a function that would be called whenever a DateTime object needed encoding. Flask would provide a default function implementation that would honor these registrations which could be passed internally to json.dumps in jsonify.

While (3) seems quite cool, it is a departure from standard json/simplejson practice, whereas (1) and (2) basically expose standard simplejson customization mechanisms to the user. How about a combination of (1) and (2), where you can specify a JSONEncoder class, or a default callback, or none of the above?


If either 1 or 2 were available, 3 could be implemented by the project or an extension.

@jfinkels jfinkels added a commit to jfinkels/flask that referenced this issue Apr 1, 2012
@jfinkels jfinkels Fix #220: adds a default JSONEncoder implementation to Flask.json_enc…
…oder_class, which users can override with their own implementation; makes jsonify use current_app.json_encoder_class as its encoder class.

Pull request #471 is a first draft of a solution based on option number 1.

By the way, there now seems to be a fair number of JSON handling functionality in flask/; should they move to their own module at some point?


Overriding jsonify with a custom function that uses my own JSONEncoder is something most if not all of my Flask projects do. Definitely +1 on the issue. @app.json_default or similar would certainly look flask-like, but it I suppose it's not clear what would happen if you use it multiple times.


This has been implemented in master, where the attribute for the custom JSONEncoder is app.json_encoder. This ticket can safely be closed.

@DasIch DasIch closed this Jul 26, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment