防止 Flask 的 jsonify 对数据进行排序

45
每次我使用jsonify,都会以字母顺序对JSON键进行排序。 我不想对键进行排序。 我能否禁用jsonify中执行的排序?

每次使用jsonify时,都会按字母表顺序对JSON键进行排序。我不想排序键。我是否可以禁用jsonify中所做的排序?

from flask import request, jsonify

@app.route('/', methods=['POST'])
def index():
    json_dict = request.get_json()
    user_id = json_dict['user_id']
    permissions = json_dict['permissions']
    data = {'user_id': user_id, 'permissions': permissions}
    return jsonify(data)

2
为什么你不想要排序后的数据?它的结构仍然相同,没有太大的区别。 - LismUK
是的,你不会依赖于JSON中键的顺序,对吧? - juanpa.arrivillaga
因为我想知道是否有可能实现,因为我想探索并且相当追求完美。 - Athul Muralidharan
如果您传递的是字典,则其顺序已经未定义,因此无法获取“按发送的值”。 - BrenBarn
根据规范,JSON对象是无序集合,言辞有点苛刻。 - juanpa.arrivillaga
4个回答

99

是的,您可以使用config属性进行修改:

app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False

需要注意的是,文档中明确警告了这一点:(链接)

默认情况下,Flask会以一种有序的方式序列化JSON对象的键。这样做是为了确保无论字典的哈希种子如何,返回值都能保持一致,从而不破坏外部HTTP缓存。您可以通过更改此变量来覆盖默认行为。尽管这不被推荐,但可能会在牺牲可缓存性的代价下提高性能。


10
需要注意的是,从Python 3.6开始,字典保留它们插入的顺序,因此文档中的参数在一般意义上不再适用。 - hynek
3
我认为应该更新答案,因为这是@hynek提供的一个重要的附注。 - Ri1a
@hynek 似乎仍在我的版本上工作,Python v3.7.3 和 Flask v1.1.1。 - Cory C
1
没有人说它不再起作用了;只是文档中引用的排序键的理由现在已经不存在了。让它留在那里可能会让新用户感到困惑。 - hynek
@hynek,我需要我的字典根据键的顺序反转。 所以我做了同样的事情并返回响应。 但是当通过 jsonify 传递时,它会回到原来的顺序。 我该如何解决这个问题? - Dinesh

3

对于 Flask 2.3+:

app = Flask(__name__)
flask.json.provider.DefaultJSONProvider.sort_keys = False

1
你好,请不要只在你的回答中提交代码,还要添加一些细节,说明为什么你认为这是最佳解决方案。 - Destroy666
这个答案中的代码不能单独运行。它在解释器中会因为"flask"的名称错误而抛出错误。我正在使用Flask 2.3.2,并且只是将顶部答案中的原始行更改为这一行。 需要额外的import flask(在我的情况下,Python的默认json包已经被导入)。 - undefined

3
从 Flask 2.2 开始,接受的答案中的 JSON_SORT_KEYS 配置选项已被弃用,并在 Flask 2.3 中移除。
截至 Flask 2.2,禁用排序的推荐方式是通过 app.json 提供者实现的。
app = Flask(__name__)
app.json.sort_keys = False

谢谢你提醒我,并且关于一个相关的问题,可以参考https://dev59.com/TrIXp4gBymzxlkE84RBW这个问题。 - mbigras

0
如果您不想更改整个API的配置,您可以使用类似这样的小函数返回一个未排序的JSON响应:
def make_unsorted_response(results_dict: dict, status_code: int):
    resp = make_response({}, status_code)
    j_string = json.dumps(results_dict, separators=(',', ':'))
    resp.set_data(value=j_string)
    return resp

我喜欢使用flask-restx,这是我如何使用这个函数的方式:
@api.route('/test', endpoint='test')
@api.doc(params={}, description="test")
class Health(Resource):
    def get(self):
        my_dict = {'z': 'z value',
                   'w': 'w value',
                   'p': 'p value'}
        results_dict = {"results": my_dict}
        return make_unsorted_response(results_dict, 200)

当被调用时,它返回一个未排序的响应,就像这样:
{"results":{"z":"z value","w":"w value","p":"p value"}}

Flask的语法基本上是一样的。如果你决定使用它,我也建议你在函数中添加一些异常处理,我只是展示了一个基本的例子。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接