Reputation: 833
I'm trying to pass sorted dictionary to jsonify() function and then use it from within JS code to take out values. What I see there is that even though I pass correct values, they are reordered by jsonify for some reason.
json_data = {
"11": {
"j_id": "out",
},
"aa": {
"j_id": "in",
},
"bb": {
"j_id": "out",
},
}
jkeys=json_data.keys()
sorted_json = sorted(jkeys, key=lambda x: json_data[x]['j_id'], reverse=False)
new_sorted=OrderedDict()
for rec in sorted_json:
new_sorted[rec]=json_data[rec]
print('sort dict: {}'.format(new_sorted))
The output is correct and I can see proper values which in my case should be: aa, 11, bb
>>> from collections import OrderedDict
>>>
>>> json_data = {
... "11": {
... "j_id": "out",
... },
... "aa": {
... "j_id": "in",
... },
... "bb": {
... "j_id": "out",
... },
... }
>>>
>>> jkeys=json_data.keys()
>>> sorted_json = sorted(jkeys, key=lambda x: json_data[x]['j_id'], reverse=False)
>>>
>>> new_sorted=OrderedDict()
>>> for rec in sorted_json:
... new_sorted[rec]=json_data[rec]
...
>>> print('sort dict: {}'.format(new_sorted))
sort dict: OrderedDict([('aa', {'j_id': 'in'}), ('11', {'j_id': 'out'}), ('bb', {'j_id': 'out'})])
Unfortunately, when I pass this to jsonify() function and then for example console.log() output of flask data, the orderd becomes like that: 11, aa, bb. Additionally to that, I've done some research and found this stackoverflow answer, leading to some good documentation notes which clearly states that setting JSON_SORT_KEYS to False is not recommended way. Then I checked this github issue and it seems that problem is not fully resolved in flask.
What would be the best way to fix it in my case?
Upvotes: 52
Views: 28421
Reputation: 2332
Add this config line to your code after the app definition:
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
Update: For Flask 2.3 and later use this:
app.json.sort_keys = False
Upvotes: 126
Reputation: 2471
Please refer to the Flask documentation 2.3.x changes (Released: 2023-04-25
)
The
JSON_AS_ASCII
,JSON_SORT_KEYS
,JSONIFY_MIMETYPE
, andJSONIFY_PRETTYPRINT_REGULAR
config keys are removed.
Version 2.3.x
has DefaultJSONProvider
class with a default parameter: sort_keys = True
To disable default JSON (dict
) key sort:
from flask import Flask
app = Flask(__name__)
app.json.sort_keys = False
Upvotes: 4
Reputation: 4576
The solution to set app.config['JSON_SORT_KEYS'] = False
no longer does the trick in the latest version of Flask (2.3), nor does it in Flask's asyncio-based sibling Quart.
The new way to turn off sorting is to update the sort_keys
attribute on the app's JSONProvider
instance:
from flask import Flask # or from quart import Quart, etc.
app = Flask(__name__)
app.json.sort_keys = False
or if you're already using a custom JSONProvider
subclass:
from flask import Flask
from flask.json.provider import DefaultJSONProvider
class CustomJSONProvider(DefaultJSONProvider):
sort_keys = False
app = Flask(__name__)
app.json = CustomJSONProvider(app)
Upvotes: 15
Reputation: 51
By default, keys from json are sorted to true. You need to override this in your project config as follows:
app.config['JSON_SORT_KEYS'] = False
Upvotes: 4
Reputation: 1121684
JSON objects are unordered structures, and your browser could easily end up discarding the order of your JSON keys again.
From the JSON standard:
An object is an unordered set of name/value pairs.
Bold emphasis mine. To remain standards compliant, use a list (JSON array) to capture a specific order.
That said, Flask can be made to preserve the order you set with OrderedDict
.
Disable sorting app-wide, with JSON_SORT_KEYS = False
.
With this setting at the default True
, jsonify()
sorts keys to provide stable HTTP responses that are cacheable. The documentation warns against disabling this only to make you aware of the downside of setting this to False
.
However, if you are using Python 3.6 or newer this concern doesn't actually play because as of that version the built-in dict
type also preserves insertion order, and so there is no problem with the order changing from one Python run to the next.
Instead of using jsonify()
, use flask.json.dumps()
directly, and create your own Response
object. Pass in sort_keys=False
:
from flask import json
response = current_app.response_class(
json.dumps(new_sorted, sort_keys=False),
mimetype=current_app.config['JSONIFY_MIMETYPE'])
Upvotes: 18