Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to keep order of sorted dictionary passed to jsonify() function?

Tags:

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?

like image 472
zerocool Avatar asked Jan 30 '19 17:01

zerocool


People also ask

Does Flask automatically Jsonify?

No, returning a dict in Flask will not apply jsonify automatically. In fact, Flask route cannot return dictionary.

What does Flask's Jsonify ()` do?

Flask jsonify is defined as a functionality within Python's capability to convert a json (JavaScript Object Notation) output into a response object with application/json mimetype by wrapping up a dumps( ) function for adding the enhancements.


2 Answers

Add this config line to your code after the app definition:

app = Flask(__name__) app.config['JSON_SORT_KEYS'] = False 
like image 136
Saeed Ir Avatar answered Sep 21 '22 05:09

Saeed Ir


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']) 
like image 28
Martijn Pieters Avatar answered Sep 19 '22 05:09

Martijn Pieters