24

I want to pass a numpy JSON serializer I wrote into Flask's jsonify function, but I cannot find a way to do this. I cannot use json.dumps, because I have to set the status_code of the Flask response when handling an error message. Is there a way to pass the JSON serializer in as a parameter, similar to using the cls parameter in json.dumps as shown here: Convert numpy type to python? My code is below; thanks.

import json
import numpy as np
from flask import Flask, jsonify

class JSON_Improved(json.JSONEncoder):
    '''
    Used to help jsonify numpy arrays or lists that contain numpy data types.
    '''
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return super(MyEncoder, self).default(obj)

app = Flask(__name__)
@app.errorhandler(ErrorMessage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response
Alex
  • 3,946
  • 11
  • 38
  • 66

3 Answers3

31

You can custom the json encoder of Flask app with app.json_encoder = JSON_Improved. JSON_Improved inherit from flask.json.JSONEncoder

class JSON_Improved(JSONEncoder):

    pass

There is a Flask Snippets about it in https://web.archive.org/web/20190128005233/http://flask.pocoo.org/snippets/119

Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
stamaimer
  • 6,227
  • 5
  • 34
  • 55
  • Thanks, that's very useful! – Alex May 25 '17 at 06:17
  • 7
    The link to the snippet is dead because all snippets were removed from the flask website. See [this issue](https://github.com/pallets/website/issues/41) on their website repo. You can get to this snippet at https://web.archive.org/web/20190128005233/http://flask.pocoo.org/snippets/119 – bigh_29 Aug 06 '19 at 19:58
10

Since json_encoder got deprecated in Flask 2.2 and would be removed in Flask 2.3, the following update might be useful.

The documentation states that:

To use a different provider, either subclass Flask and set json_provider_class to a provider class, or set app.json to an instance of the class.

In my case, assigning the only json_provider_class wasn't sufficient. But either of the following worked:

app = Flask(__name__)
app.json_provider_class = CustomJSONProvider
app.json = CustomJSONProvider(app)

or just:

app = Flask(__name__)
app.json = CustomJSONProvider(app)

Given the already defined JSON_Improved encoder, sample class CustomJSONProvider would be:

from flask.json.provider import JSONProvider


class CustomJSONProvider(JSONProvider):

    def dumps(self, obj, **kwargs):
        return json.dumps(obj, **kwargs, cls=JSON_Improved)

    def loads(self, s: str | bytes, **kwargs):
        return json.loads(s, **kwargs)
First Last
  • 73
  • 4
Dmitry
  • 155
  • 1
  • 7
  • I used your approach and one deprecation warning disappeared, but the log still says: 'JSONEncoder' is deprecated and will be removed in Flask 2.3. Use 'Flask.json' to provide an alternate JSON implementation instead. Makes sense since the JSON_Improved class still inherits from JSONEncoder. – JWo Mar 13 '23 at 03:29
  • 1
    I suggest that `JSONEncoder` should be imported directly from `json` module, not the `flask.json`. – Dmitry Mar 13 '23 at 11:54
0
For connexion implementation:
...
from flask.json import JSONEncoder
from flask.json.provider import JSONProvider
import json
...

...from Dmitry
class CustomJSONProvider(JSONProvider):

    def dumps(self, obj, **kwargs):
        return json.dumps(obj, **kwargs, cls=JSON_Improved)

    def loads(self, s: str | bytes, **kwargs):
        return json.loads(s, **kwargs)

...
    app = connexion.App(__name__, specification_dir='.//')
    app.app.json = CustomJSONProvider(app.app)
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 28 '23 at 10:10