如何使用Python 3 json.dumps修复JSON密钥顺序?

bbe*_*ort 7 python json python-3.x

我注意到Python 3的实现有一些奇怪的行为json.dumps,即每次将同一个对象从执行转储到执行时,键顺序都会改变.谷歌搜索没有工作,因为我不关心按键排序,我只是希望它们保持不变!这是一个示例脚本:

import json

data = {
    'number': 42,
    'name': 'John Doe',
    'email': 'john.doe@example.com',
    'balance': 235.03,
    'isadmin': False,
    'groceries': [
        'apples',
        'bananas',
        'pears',
    ],
    'nested': {
        'complex': True,
        'value': 2153.23412
    }
}

print(json.dumps(data, indent=2))
Run Code Online (Sandbox Code Playgroud)

当我运行此脚本时,每次都会得到不同的输出,例如:

$ python print_data.py 
{
  "groceries": [
    "apples",
    "bananas",
    "pears"
  ],
  "isadmin": false,
  "nested": {
    "value": 2153.23412,
    "complex": true
  },
  "email": "john.doe@example.com",
  "number": 42,
  "name": "John Doe",
  "balance": 235.03
}
Run Code Online (Sandbox Code Playgroud)

但后来我再次运行它,我得到:

$ python print_data.py 
{
  "email": "john.doe@example.com",
  "balance": 235.03,
  "name": "John Doe",
  "nested": {
    "value": 2153.23412,
    "complex": true
  },
  "isadmin": false,
  "groceries": [
    "apples",
    "bananas",
    "pears"
  ],
  "number": 42
}
Run Code Online (Sandbox Code Playgroud)

我知道字典是无序集合,并且顺序基于散列函数; 但是在Python 2中 - 顺序(无论它是什么)是固定的,并且不会在每次执行的基础上改变.这里的困难在于它使我的测试难以运行,因为我需要比较两个不同模块的JSON输出!

知道发生了什么事吗?怎么解决?请注意,我想避免使用OrderedDict或执行任何排序,重要的是字符串表示在执行之间保持不变.此外,这仅用于测试目的,对我的模块的实现没有任何影响.

Mar*_*ers 9

Python字典和JSON对象是无序的.您可以要求json.dumps()对输出中的键进行排序; 这是为了方便测试.使用sort_keys参数True:

print(json.dumps(data, indent=2, sort_keys=True))
Run Code Online (Sandbox Code Playgroud)

请参阅为什么Python字典中的顺序和设置是任意的?至于为什么每次都看到不同的订单.

您可以将PYTHONHASHSEED环境变量设置为整数值以"锁定"字典顺序; 使用它只运行测试而不是生产,因为哈希随机化的重点是防止攻击者轻易地对你的程序进行DOS操作.

  • @bbengfort:您可以将[`PYTHONHASHSEED`环境变量](https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED)设置为整数值. (2认同)