Skip to content

Commit 74b3f7e

Browse files
authored
Merge pull request pallets#1898 from RaHus/per_blueprint_jsoncoding_#1710
Per blueprint jsoncoding pallets#1710
2 parents 8d515a6 + 4305ebd commit 74b3f7e

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

flask/blueprints.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ class Blueprint(_PackageBoundObject):
8989
warn_on_modifications = False
9090
_got_registered_once = False
9191

92+
#: Blueprint local JSON decoder class to use.
93+
# Set to None to use the :class:`~flask.app.Flask.json_encoder`.
94+
json_encoder = None
95+
#: Blueprint local JSON decoder class to use.
96+
# Set to None to use the :class:`~flask.app.Flask.json_decoder`.
97+
json_decoder = None
98+
9299
def __init__(self, name, import_name, static_folder=None,
93100
static_url_path=None, template_folder=None,
94101
url_prefix=None, subdomain=None, url_defaults=None,

flask/json.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from datetime import date
1414
from .globals import current_app, request
1515
from ._compat import text_type, PY2
16+
from .ctx import has_request_context
1617

1718
from werkzeug.http import http_date
1819
from jinja2 import Markup
@@ -91,7 +92,11 @@ class JSONDecoder(_json.JSONDecoder):
9192
def _dump_arg_defaults(kwargs):
9293
"""Inject default arguments for dump functions."""
9394
if current_app:
94-
kwargs.setdefault('cls', current_app.json_encoder)
95+
bp = current_app.blueprints.get(request.blueprint,
96+
None) if has_request_context() else None
97+
kwargs.setdefault('cls',
98+
bp.json_encoder if bp and bp.json_encoder
99+
else current_app.json_encoder)
95100
if not current_app.config['JSON_AS_ASCII']:
96101
kwargs.setdefault('ensure_ascii', False)
97102
kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS'])
@@ -103,7 +108,11 @@ def _dump_arg_defaults(kwargs):
103108
def _load_arg_defaults(kwargs):
104109
"""Inject default arguments for load functions."""
105110
if current_app:
106-
kwargs.setdefault('cls', current_app.json_decoder)
111+
bp = current_app.blueprints.get(request.blueprint,
112+
None) if has_request_context() else None
113+
kwargs.setdefault('cls',
114+
bp.json_decoder if bp and bp.json_decoder
115+
else current_app.json_decoder)
107116
else:
108117
kwargs.setdefault('cls', JSONDecoder)
109118

tests/test_helpers.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,41 @@ def index():
267267
}), content_type='application/json')
268268
assert rv.data == b'"<42>"'
269269

270+
def test_blueprint_json_customization(self):
271+
class X(object):
272+
def __init__(self, val):
273+
self.val = val
274+
class MyEncoder(flask.json.JSONEncoder):
275+
def default(self, o):
276+
if isinstance(o, X):
277+
return '<%d>' % o.val
278+
return flask.json.JSONEncoder.default(self, o)
279+
class MyDecoder(flask.json.JSONDecoder):
280+
def __init__(self, *args, **kwargs):
281+
kwargs.setdefault('object_hook', self.object_hook)
282+
flask.json.JSONDecoder.__init__(self, *args, **kwargs)
283+
def object_hook(self, obj):
284+
if len(obj) == 1 and '_foo' in obj:
285+
return X(obj['_foo'])
286+
return obj
287+
288+
blue = flask.Blueprint('blue', __name__)
289+
blue.json_encoder = MyEncoder
290+
blue.json_decoder = MyDecoder
291+
@blue.route('/bp', methods=['POST'])
292+
def index():
293+
return flask.json.dumps(flask.request.get_json()['x'])
294+
295+
app = flask.Flask(__name__)
296+
app.testing = True
297+
app.register_blueprint(blue)
298+
299+
c = app.test_client()
300+
rv = c.post('/bp', data=flask.json.dumps({
301+
'x': {'_foo': 42}
302+
}), content_type='application/json')
303+
assert rv.data == b'"<42>"'
304+
270305
def test_modified_url_encoding(self):
271306
class ModifiedRequest(flask.Request):
272307
url_charset = 'euc-kr'

0 commit comments

Comments
 (0)