Как полностью отсортировать дерево JSON по алфавиту

#python #json #sorting

#python #json #сортировка

Вопрос:

Мне нужно выполнить полный рекурсивный алфавитный порядок для объекта JSON в python.

Причина в том, чтобы иметь возможность различать два файла 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"
}
 

РЕДАКТИРОВАТЬ: чтобы иметь возможность выполнять различие, он также должен упорядочивать элементы массива.

Ответ №1:

Для этого вы можете использовать json.dump/s собственный kwarg sort_keys .

 a_json = json.dumps(json_object, sort_keys=True)
print(a_json)
 

Комментарии:

1. sort_keys сортирует ключи, но не значения массива, поэтому недостаточно различать два файла json. Я уточнил свой вопрос.

Ответ №2:

Объект JSON — это простой объект dict. До версии 3.7 у dicts не было порядка, поэтому сначала вам нужно преобразовать его в OrderedDict, а затем добавить каждый элемент json в правильном порядке. порядок. С 3.7 вы можете полагаться на стандартный порядок dict .

Объекты с ключами сортируются в соответствии с их ключами, объекты внутри списка сортируются по их «отсортированному рекурсивному строковому представлению», в то время как примитивные значения сортируются в соответствии с их естественным порядком.

 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))
 

Комментарии:

1. Формально порядок @superbrain гарантируется только с версии 3.7 (в 3.6 на него «не следует полагаться»). Я исправлю свой ответ, чтобы было понятно.

2. @superbrain разумно иметь это в виду, если вы хотите изменить код python старше двух с половиной лет. Возможно, это все еще большая часть кода python.