diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index d42000260..f75cb0858 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -348,6 +348,14 @@ When set to `False`, JSON rendering and parsing will be permissive. However, the Default: `True` +#### SORT_KEYS_JSON + +When set to `True`, Keys will be sorted before JSON rendering (see json.dumps sort_keys) + +When set to `False`, Keys will be sorted before JSON rendering (see json.dumps sort_keys) + +Default: `False` + #### COERCE_DECIMAL_TO_STRING When returning decimal objects in API representations that do not support a native decimal type, it is normally best to return the value as a string. This avoids the loss of precision that occurs with binary floating point implementations. diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 5b7ba8a8c..ae2cb88e4 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -60,6 +60,7 @@ class JSONRenderer(BaseRenderer): ensure_ascii = not api_settings.UNICODE_JSON compact = api_settings.COMPACT_JSON strict = api_settings.STRICT_JSON + sort_keys = api_settings.SORT_KEYS_JSON # We don't set a charset because JSON is a binary encoding, # that can be encoded as utf-8, utf-16 or utf-32. @@ -100,7 +101,7 @@ class JSONRenderer(BaseRenderer): ret = json.dumps( data, cls=self.encoder_class, indent=indent, ensure_ascii=self.ensure_ascii, - allow_nan=not self.strict, separators=separators + allow_nan=not self.strict, separators=separators, sort_keys=self.sort_keys ) # We always fully escape \u2028 and \u2029 to ensure we output JSON diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 9eb4c5653..71875deac 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -111,6 +111,7 @@ DEFAULTS = { 'UNICODE_JSON': True, 'COMPACT_JSON': True, 'STRICT_JSON': True, + 'SORT_KEYS_JSON': False, 'COERCE_DECIMAL_TO_STRING': True, 'UPLOADED_FILES_USE_URL': True, diff --git a/tests/test_renderers.py b/tests/test_renderers.py index 8271608e1..7d3e41156 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -391,6 +391,13 @@ class JSONRendererTests(TestCase): content = renderer.render(obj, 'application/json; indent=2') self.assertEqual(strip_trailing_whitespace(content.decode()), _indented_repr) + @override_settings(REST_FRAMEWORK={'SORT_KEYS_JSON': True}) + def test_sort_keys_json(self): + obj = {'2': {'c': 1, 'b': 2, 'a': 3 }, '1': None} + renderer = JSONRenderer() + content = renderer.render(obj, 'application/json') + self.assertEqual(content.decode(), '{"1": null, "2": {"a": 3, "b": 2, "c": 1}}') + class UnicodeJSONRendererTests(TestCase): """