flask-restx icon indicating copy to clipboard operation
flask-restx copied to clipboard

use flask machinery for json

Open ancieg opened this issue 11 months ago • 1 comments

flask-restx lacks of ability to switch JSON [de]serializer. I prepared small patch to use flask machinery for JSON.

Usage example:

import logging
from datetime import datetime

import sdjson

from flask import Flask, current_app
from flask.json.provider import JSONProvider
from flask_restx import Api, Resource

logging.basicConfig(level=logging.INFO)


class SDJSONProvider(JSONProvider):
    def dumps(self, obj, **kwargs):
        current_app.logger.info("SDJSONProvider.dumps()")
        return sdjson.dumps(obj, default=str)

    def loads(self, s, **kwargs):
        current_app.logger.info("SDJSONProvider.loads()")
        return sdjson.loads(s, **kwargs)


class MyApp(Flask):
    json_provider_class = SDJSONProvider


app = MyApp(__name__)
api = Api(app)


@api.route("/date")
class DateResource(Resource):
    def get(self):
        return {"current_date": datetime.now()}


if __name__ == "__main__":
    app.run(debug=True)

another usage example:

import logging
from datetime import datetime

import sdjson

from flask import Flask, current_app
from flask.json.provider import JSONProvider
from flask_restx import Api, Resource, fields

logging.basicConfig(level=logging.INFO)


class SDJSONProvider(JSONProvider):
    def dumps(self, obj, **kwargs):
        current_app.logger.info("SDJSONProvider.dumps()")
        return sdjson.dumps(obj, default=SDJSONProvider._default)

    def loads(self, s, **kwargs):
        current_app.logger.info("SDJSONProvider.loads()")
        return sdjson.loads(s, **kwargs)

    @staticmethod
    def _default(obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)


app = Flask(__name__)
app.json = SDJSONProvider(app)
api = Api(app)

hello_model = api.model(
    "Hello", {"name": fields.String(required=True, description="Your name")}
)


@api.route("/hello")
@api.expect(hello_model)
class HelloResource(Resource):
    def post(self):
        current_app.logger.info(api.payload)
        name = api.payload["name"]
        return (
            {
                "response": f"Hello, {name}!",
                "current_date": datetime.now(),
            },
            201,
        )


if __name__ == "__main__":
    app.run(debug=True)

ancieg avatar Dec 26 '24 16:12 ancieg

For me the proposition makes sense

engFelipeMonteiro avatar Feb 15 '25 15:02 engFelipeMonteiro