Skip to content

Commit

Permalink
let the user choose a custom json serializer through the RESTPLUS_JSO…
Browse files Browse the repository at this point in the history
…N_SERIALIZER config option
  • Loading branch information
ziirish committed May 6, 2019
1 parent bee950a commit c3d8741
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
49 changes: 49 additions & 0 deletions doc/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,55 @@ parameter to some classes or function to force order preservation:
- globally on :class:`Namespace`: ``ns = Namespace(ordered=True)``
- locally on :func:`marshal`: ``return marshal(data, fields, ordered=True)``

Configuration
-------------

The following configuration options exist for Flask-RESTPlus:

============================ =============== ==================================
OPTION DEFAULT VALUE DESCRIPTION
============================ =============== ==================================
``BUNDLE_ERRORS`` ``False`` Bundle all the validation errors
instead of returning only the
first one encountered.
See the `Error Handling
<parsing.html#error-handling>`__
section of the documentation for
details.
``RESTPLUS_VALIDATE`` ``False`` Whether to enforce payload
validation by default when using
the ``@api.expect()`` decorator.
See the `@api.expect()
<swagger.html#the-api-expect-decorator>`__
documentation for details.
``RESTPLUS_MASK_HEADER`` ``X-Fields`` Choose the name of the *Header*
that will contain the masks to
apply to your answer.
See the `Fields masks <mask.html>`__
documentation for details.
``RESTPLUS_MASK_SWAGGER`` ``True`` Whether to enable the mask
documentation in your swagger or
not.
See the `mask usage
<mask.html#usage>`__ documentation
for details.
``RESTPLUS_JSON`` ``{}`` Dictionary of options to pass to
the json *serializer* (by default
``json.dumps``).
``RESTPLUS_JSON_SERIALIZER`` ``None`` Here you can choose your
own/preferred json *serializer*.
You can either specify the name
of the module (example: ``ujson``)
or you can give the full name of
your *serializer* (example:
``ujson.dumps``).

.. note::
If you only specify the module
name the default Flask-RESTPLUS
behavior is to import its
``dumps`` method.
============================ =============== ==================================

Full example
------------
Expand Down
19 changes: 18 additions & 1 deletion flask_restplus/representations.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import

import importlib

from json import dumps

from flask import make_response, current_app

serializer = None


def output_json(data, code, headers=None):
'''Makes a Flask response with a JSON encoded body'''

global serializer

settings = current_app.config.get('RESTPLUS_JSON', {})
custom_serializer = current_app.config.get('RESTPLUS_JSON_SERIALIZER', None)

# If the user wants to use a custom serializer, let it be
if serializer is None and custom_serializer:
try:
serializer = importlib.import_module("{}.dumps".format(custom_serializer) if '.' not in custom_serializer
else custom_serializer)
except ImportError:
serializer = dumps
elif serializer is None:
serializer = dumps

# If we're in debug mode, and the indent is not set, we set it to a
# reasonable value here. Note that this won't override any existing value
Expand All @@ -19,7 +36,7 @@ def output_json(data, code, headers=None):

# always end the json dumps with a new line
# see https://github.com/mitsuhiko/flask/pull/1262
dumped = dumps(data, **settings) + "\n"
dumped = serializer(data, **settings) + "\n"

resp = make_response(dumped, code)
resp.headers.extend(headers or {})
Expand Down
1 change: 1 addition & 0 deletions requirements/test.pip
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pytest-mock==1.6.3
pytest-profiling==1.2.11
pytest-sugar==0.9.0
tzlocal
ujson
22 changes: 22 additions & 0 deletions tests/test_representations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import flask_restplus.representations as rep

from json import dumps, loads
from ujson import dumps as udumps, loads as uloads

from flask import current_app


def test_representations(api):
payload = {
'id': 1,
'name': 'toto',
'address': 'test',
}
r = rep.output_json(payload, 200)
assert loads(r.get_data(True)) == loads(dumps(payload))
# now reset serializer
rep.serializer = None
# then enforce a custom serializer
current_app.config['RESTPLUS_JSON_SERIALIZER'] = 'ujson'
r2 = rep.output_json(payload, 200)
assert uloads(r2.get_data(True)) == uloads(udumps(payload))

0 comments on commit c3d8741

Please sign in to comment.