Order JSON keys by default to avoid trashing HTTP caches

This commit is contained in:
Armin Ronacher 2013-06-01 19:24:03 +01:00
parent 3d9055b3b7
commit 77d293cf49
5 changed files with 57 additions and 1 deletions

View file

@ -63,6 +63,8 @@ Release date to be decided.
more reliable in case something handles an exception halfway through
the error handling process.
- Added the ``JSONIFY_PRETTYPRINT_REGULAR`` configuration variable.
- Flask now orders JSON keys by default to not trash HTTP caches due to
different hash seeds between different workers.
Version 0.9
-----------

View file

@ -149,6 +149,17 @@ The following configuration values are used internally by Flask:
unicode strings. ``jsonfiy`` will
automatically encode it in ``utf-8``
then for transport for instance.
``JSON_SORT_KEYS`` By default Flask will serialize JSON
objects in a way that the keys are
ordered. This is done in order to
ensure that independent of the hash seed
of the dictionary the return value will
be consistent to not trash external HTTP
caches. You can override the default
behavior by changing this variable.
This is not recommended but might give
you a performance improvement on the
cost of cachability.
``JSONIFY_PRETTYPRINT_REGULAR`` If this is set to ``True`` (the default)
jsonify responses will be pretty printed
if they are not requested by an
@ -197,7 +208,7 @@ The following configuration values are used internally by Flask:
``PREFERRED_URL_SCHEME``
.. versionadded:: 0.10
``JSON_AS_ASCII``, ``JSONIFY_PRETTYPRINT_REGULAR``
``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_PRETTYPRINT_REGULAR``
Configuring from Files
----------------------

View file

@ -291,6 +291,7 @@ class Flask(_PackageBoundObject):
'TRAP_HTTP_EXCEPTIONS': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
})

View file

@ -92,10 +92,12 @@ class JSONDecoder(_json.JSONDecoder):
def _dump_arg_defaults(kwargs):
"""Inject default arguments for dump functions."""
kwargs.setdefault('sort_keys', True)
if current_app:
kwargs.setdefault('cls', current_app.json_encoder)
if not current_app.config['JSON_AS_ASCII']:
kwargs.setdefault('ensure_ascii', False)
kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS'])
def _load_arg_defaults(kwargs):

View file

@ -148,6 +148,46 @@ class JSONTestCase(FlaskTestCase):
if not has_encoding('euc-kr'):
test_modified_url_encoding = None
def test_json_key_sorting(self):
app = flask.Flask(__name__)
app.testing = True
self.assert_equal(app.config['JSON_SORT_KEYS'], True)
d = dict.fromkeys(range(20), 'foo')
@app.route('/')
def index():
return flask.jsonify(values=d)
c = app.test_client()
rv = c.get('/')
lines = [x.strip() for x in rv.data.strip().decode('utf-8').splitlines()]
self.assert_equal(lines, [
'{',
'"values": {',
'"0": "foo",',
'"1": "foo",',
'"2": "foo",',
'"3": "foo",',
'"4": "foo",',
'"5": "foo",',
'"6": "foo",',
'"7": "foo",',
'"8": "foo",',
'"9": "foo",',
'"10": "foo",',
'"11": "foo",',
'"12": "foo",',
'"13": "foo",',
'"14": "foo",',
'"15": "foo",',
'"16": "foo",',
'"17": "foo",',
'"18": "foo",',
'"19": "foo"',
'}',
'}'
])
class SendfileTestCase(FlaskTestCase):