elelias
elelias

Reputation: 4779

json serialisation of dates on flask restful

I have the following resource:

class Image(Resource):
    def get(self, db_name, col_name, image_id):
        col = mongo_client[db_name][col_name]
        image = col.find_one({'_id':ObjectId(image_id)})
        try:
            image['_id'] = str(image['_id'])
        except TypeError:
            return {'image': 'notFound'}
        return {'image':image}

linked to a certain endpoint.

However, image contains certain datetime objects inside. I could wrap this around with `json.dumps(..., default=str), but I see that there is a way of enforcing this on flask-restful. It's just not clear to me what exactly needs to be done.

In particular, I read:

    It is possible to configure how the default Flask-RESTful JSON
    representation will format JSON by providing a RESTFUL_JSON
    attribute on the application configuration. 
    This setting is a dictionary with keys that 
     correspond to the keyword arguments of json.dumps().

class MyConfig(object):
    RESTFUL_JSON = {'separators': (', ', ': '),
                    'indent': 2,
                    'cls': MyCustomEncoder}

But it's not clear to me where exactly this needs to be placed. Tried a few things and it didn't work.

EDIT:

I finally solved with this:

Right after

api = Api(app)

I added:

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            #return int(obj.strftime('%s'))
            return str(obj)
        elif isinstance(obj, datetime.date):
            #return int(obj.strftime('%s'))
            return str(obj)
        return json.JSONEncoder.default(self, obj)


def custom_json_output(data, code, headers=None):
    dumped = json.dumps(data, cls=CustomEncoder)
    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return resp

api = Api(app)
api.representations.update({
    'application/json': custom_json_output
})

Upvotes: 8

Views: 1925

Answers (2)

Konstantinos Katsantonis
Konstantinos Katsantonis

Reputation: 1450

Just cleared this out, you just have to do the following:

app = Flask(__name__)
api = Api(app)
app.config['RESTFUL_JSON'] = {'cls':MyCustomEncoder}

This works both for plain Flask and Flask-RESTful.

NOTES:

1) Apparently the following part of the documentation is not that clear:

It is possible to configure how the default Flask-RESTful JSON representation will format JSON by providing a RESTFUL_JSON attribute on the application configuration. This setting is a dictionary with keys that correspond to the keyword arguments of json.dumps().

class MyConfig(object):
    RESTFUL_JSON = {'separators': (', ', ': '),
                    'indent': 2,
                    'cls': MyCustomEncoder}

2)Apart from the 'cls' argument you can actually overwrite any keyword argument of the json.dumps function.

Upvotes: 3

rtkaleta
rtkaleta

Reputation: 691

Having created a Flask app, e.g. like so:

root_app = Flask(__name__)

place MyConfig in some module e.g. config.py and then configure root_app like:

root_app.config.from_object('config.MyConfig')

Upvotes: 0

Related Questions