如何完全按字母顺序对JSON树进行排序

3
我需要在Python中对一个JSON对象进行完整的递归字母顺序排序。目的是为了能够比较两个JSON文件。
给定以下输入:
{
    "request-id": "12345",
    "version": "1.1.4",
    "multi": {
            "one": 1, 
            "two": 2.0,
            "Abc": [3,2,4,1, null],
            "three": null,
            "list": [
                        {"lb1": 2.1},
                        {"lb": 2.2}, 
                        {"la": 3}, 
                        {"mix_list": [1, {"bb":1}, 2, {"aa":1}]}]
        }
}

这是预期的输出结果:

{
    "multi": {
        "Abc": [1,2,3,4,null],
        "list": [
            {"la": 3},
            {"lb": 2.2},
            {"lb1": 2.1},
            { "mix_list": [1, 2, {"aa": 1}, {"bb": 1}] }
        ],
        "one": 1,
        "three": null,
        "two": 2.0
    },
    "request-id": "12345",
    "version": "1.1.4"
}

编辑:为了能够进行差异比较,它还应该对数组元素进行排序。

2个回答

2
一个JSON对象是一个简单的字典对象。在3.7版本之前,字典没有顺序,因此您需要先将其转换为OrderedDict,然后按正确顺序附加每个json元素。从3.7+开始,您可以依赖于标准字典排序。
具有键的对象根据它们的键进行排序,列表中的对象根据它们的“排序递归字符串表示”进行排序,而原始值根据它们的自然排序进行排序。
import json
from operator import itemgetter

# replace all three {} with OrderedDict() for python <= 3.6

def sorted_json(js, result):

    def norm_str(s):
        # because of str special handling of single quotes
        return str(s).replace("'", '"')

    if type(js) in [int, str, bool, float] or js is None:
        return js

    if type(js) == list:
        res = [sorted_json(i, {}) for i in js]
        return sorted(res, key=norm_str)

    items = sorted(js.items(), key=itemgetter(0))
    for k, v in items:
        result[k] = sorted_json(v, {})

    return result

排序区分大小写。

您可以这样使用:

json_data = json.loads(json_text)
res = sorted_json(json_data, {})
print(json.dumps(res, indent=4))

@superbrain 从3.7版本开始,订单正式得到保证(在3.6中,“不应依赖此功能”)。我会修改我的答案以使其更清晰明了。 - lorenzo
@superbrain,记住这一点是明智的,以防你想修改两年半以前的Python代码。这可能涵盖了大部分Python代码。 - loa_in_

2
您可以使用json.dump/s原生参数sort_keys来实现这一点。
a_json = json.dumps(json_object, sort_keys=True)
print(a_json)

2
sort_keys 仅对键进行排序,而不是数组值,因此它不足以区分两个 JSON 文件。我澄清了我的问题。 - lorenzo

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