json.dumps 的 sort_keys 参数仅支持默认Unicode字典序,不支持自定义排序;需通过预处理字典或继承JSONEncoder实现灵活排序,但后者对嵌套字典无效。

json.dumps 的 sort_keys 参数只能启用默认字典序
默认情况下,json.dumps 会把字典键按 Unicode 码点升序排列(即 sort_keys=True),但不支持传入自定义比较函数或 key 函数。这是 Python 标准库的限制 —— json 模块底层用的是 sorted(obj.keys()),没有暴露 key= 参数。
用 sorted() 预处理字典再传给 json.dumps
最直接、兼容性最好的方式是手动对字典键排序,构造一个新字典(保持插入顺序),再交给 json.dumps。Python 3.7+ 中字典保持插入顺序,所以这个方法可靠。
常见场景包括:按业务优先级排键(如把 "id" 放最前)、按长度排序、忽略大小写、或按白名单顺序固定字段位置。
- 按字母逆序:
{k: v for k, v in sorted(d.items(), key=lambda x: x[0], reverse=True)} - 按白名单顺序(缺失键放最后):
order = ["id", "name", "email"]; sorted_items = sorted(d.items(), key=lambda kv: (order.index(kv[0]) if kv[0] in order else len(order), kv[0])) - 忽略大小写排序:
sorted(d.items(), key=lambda x: x[0].lower())
用 json.JSONEncoder 子类实现更灵活的控制
如果需要在多处复用同一套排序逻辑,或者想影响嵌套字典的键序,可以继承 json.JSONEncoder 并重写 encode() 或利用 default() 预处理。但注意:JSONEncoder 不直接接收原始字典对象,而是逐层调用,所以稳妥做法是在 encode() 入口做一次预处理。
示例(仅对顶层 dict 排序):
自定义设置的程度更高可以满足大部分中小型企业的建站需求,同时修正了上一版中发现的BUG,优化了核心的代码占用的服务器资源更少,执行速度比上一版更快 主要的特色功能如下: 1)特色的菜单设置功能,菜单设置分为顶部菜单和底部菜单,每一项都可以进行更名、选择是否隐 藏,排序等。 2)增加企业基本信息设置功能,输入的企业信息可以在网页底部的醒目位置看到。 3)增加了在线编辑功能,输入产品信息,企业介绍等栏
class SortedKeysEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, dict):
obj = {k: obj[k] for k in sorted(obj.keys(), key=str.lower)}
return super().encode(obj)
调用:json.dumps(data, cls=SortedKeysEncoder)。注意:此方式对嵌套 dict 无效,需递归处理 —— 若真有深层需求,建议改用预处理函数而非 encoder。
容易被忽略的坑:排序后丢失原始类型或触发不可预期行为
手动排序时,若字典键本身不是字符串(比如 int、tuple),sorted() 可能抛 TypeError;而 json.dumps 本身只接受字符串键,所以实际中几乎不会遇到非 str 键 —— 但如果你在排序逻辑里用了 .lower() 或其他字符串方法,务必先确保 k 是 str 类型。
另一个细节:某些序列化工具(如 orjson、ujson)不支持 cls 参数,也不认 sort_keys 的扩展,此时只能走预处理路线。
真正复杂的排序逻辑(比如依赖外部配置、动态权重)别塞进 json.dumps 调用链里,单独写个 sort_dict_keys(data, key_func) 函数,语义清晰也方便单元测试。









