Alex
Alex

Reputation: 4264

Pass user built json encoder into Flask's jsonify

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

Upvotes: 28

Views: 21101

Answers (3)

dimakin
dimakin

Reputation: 1978

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.

So, in the case of derived class, the solution would be:

class MyFlask(Flask):
    json_provider_class = CustomJSONProvider

app = MyFlask(__name__)

or, in the case of instantiating class Flask directly, 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)

Upvotes: 20

user3149757
user3149757

Reputation: 1

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)

Upvotes: 0

stamaimer
stamaimer

Reputation: 6485

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

Upvotes: 30

Related Questions