Browse Source

clean up blueprint json support

add changelog for #1898
pull/1676/merge
David Lord 8 years ago
parent
commit
46f83665ef
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
  1. 3
      CHANGES
  2. 4
      flask/blueprints.py
  3. 24
      flask/json.py
  4. 16
      tests/test_helpers.py

3
CHANGES

@ -27,8 +27,11 @@ Major release, unreleased
- ``MethodView`` can inherit method handlers from base classes. (`#1936`_) - ``MethodView`` can inherit method handlers from base classes. (`#1936`_)
- Errors caused while opening the session at the beginning of the request are - Errors caused while opening the session at the beginning of the request are
handled by the app's error handlers. (`#2254`_) handled by the app's error handlers. (`#2254`_)
- Blueprints gained ``json_encoder`` and ``json_decoder`` attributes to
override the app's encoder and decoder. (`#1898`_)
.. _#1489: https://github.com/pallets/flask/pull/1489 .. _#1489: https://github.com/pallets/flask/pull/1489
.. _#1898: https://github.com/pallets/flask/pull/1898
.. _#1936: https://github.com/pallets/flask/pull/1936 .. _#1936: https://github.com/pallets/flask/pull/1936
.. _#2017: https://github.com/pallets/flask/pull/2017 .. _#2017: https://github.com/pallets/flask/pull/2017
.. _#2223: https://github.com/pallets/flask/pull/2223 .. _#2223: https://github.com/pallets/flask/pull/2223

4
flask/blueprints.py

@ -90,10 +90,10 @@ class Blueprint(_PackageBoundObject):
_got_registered_once = False _got_registered_once = False
#: Blueprint local JSON decoder class to use. #: Blueprint local JSON decoder class to use.
# Set to None to use the :class:`~flask.app.Flask.json_encoder`. #: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_encoder`.
json_encoder = None json_encoder = None
#: Blueprint local JSON decoder class to use. #: Blueprint local JSON decoder class to use.
# Set to None to use the :class:`~flask.app.Flask.json_decoder`. #: Set to ``None`` to use the app's :class:`~flask.app.Flask.json_decoder`.
json_decoder = None json_decoder = None
def __init__(self, name, import_name, static_folder=None, def __init__(self, name, import_name, static_folder=None,

24
flask/json.py

@ -92,13 +92,16 @@ class JSONDecoder(_json.JSONDecoder):
def _dump_arg_defaults(kwargs): def _dump_arg_defaults(kwargs):
"""Inject default arguments for dump functions.""" """Inject default arguments for dump functions."""
if current_app: if current_app:
bp = current_app.blueprints.get(request.blueprint, bp = current_app.blueprints.get(request.blueprint) if request else None
None) if has_request_context() else None kwargs.setdefault(
kwargs.setdefault('cls', 'cls',
bp.json_encoder if bp and bp.json_encoder bp.json_encoder if bp and bp.json_encoder
else current_app.json_encoder) else current_app.json_encoder
)
if not current_app.config['JSON_AS_ASCII']: if not current_app.config['JSON_AS_ASCII']:
kwargs.setdefault('ensure_ascii', False) kwargs.setdefault('ensure_ascii', False)
kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS']) kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS'])
else: else:
kwargs.setdefault('sort_keys', True) kwargs.setdefault('sort_keys', True)
@ -108,11 +111,12 @@ def _dump_arg_defaults(kwargs):
def _load_arg_defaults(kwargs): def _load_arg_defaults(kwargs):
"""Inject default arguments for load functions.""" """Inject default arguments for load functions."""
if current_app: if current_app:
bp = current_app.blueprints.get(request.blueprint, bp = current_app.blueprints.get(request.blueprint) if request else None
None) if has_request_context() else None kwargs.setdefault(
kwargs.setdefault('cls', 'cls',
bp.json_decoder if bp and bp.json_decoder bp.json_decoder if bp and bp.json_decoder
else current_app.json_decoder) else current_app.json_decoder
)
else: else:
kwargs.setdefault('cls', JSONDecoder) kwargs.setdefault('cls', JSONDecoder)

16
tests/test_helpers.py

@ -271,30 +271,36 @@ class TestJSON(object):
class X(object): class X(object):
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
class MyEncoder(flask.json.JSONEncoder): class MyEncoder(flask.json.JSONEncoder):
def default(self, o): def default(self, o):
if isinstance(o, X): if isinstance(o, X):
return '<%d>' % o.val return '<%d>' % o.val
return flask.json.JSONEncoder.default(self, o) return flask.json.JSONEncoder.default(self, o)
class MyDecoder(flask.json.JSONDecoder): class MyDecoder(flask.json.JSONDecoder):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs.setdefault('object_hook', self.object_hook) kwargs.setdefault('object_hook', self.object_hook)
flask.json.JSONDecoder.__init__(self, *args, **kwargs) flask.json.JSONDecoder.__init__(self, *args, **kwargs)
def object_hook(self, obj): def object_hook(self, obj):
if len(obj) == 1 and '_foo' in obj: if len(obj) == 1 and '_foo' in obj:
return X(obj['_foo']) return X(obj['_foo'])
return obj return obj
blue = flask.Blueprint('blue', __name__) bp = flask.Blueprint('bp', __name__)
blue.json_encoder = MyEncoder bp.json_encoder = MyEncoder
blue.json_decoder = MyDecoder bp.json_decoder = MyDecoder
@blue.route('/bp', methods=['POST'])
@bp.route('/bp', methods=['POST'])
def index(): def index():
return flask.json.dumps(flask.request.get_json()['x']) return flask.json.dumps(flask.request.get_json()['x'])
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.testing = True app.testing = True
app.register_blueprint(blue) app.register_blueprint(bp)
c = app.test_client() c = app.test_client()
rv = c.post('/bp', data=flask.json.dumps({ rv = c.post('/bp', data=flask.json.dumps({

Loading…
Cancel
Save