Как я могу сохранить порядок OrderedDict при преобразовании его в JSON

Я пишу REST API в python3 с использованием flask, и я изо всех сил пытался найти способ вернуть dict как json, сохраняя порядок ключей. Я использую OrderedDict, потому что, очевидно, встроенный словарь не сохраняет порядок элементов.

У меня есть метод, который выглядит так:

@app.route('/foobar', methods=['GET'])
def foobar()
    data = [OrderedDict([("a",1),
        ("b",2),
        ("c",3)])]
    return jsonify(data),200

И вот пример вывода, который я мог получить:

[{"b":2,"c":3,"a":1}]

Вот что я хочу получить:

[{"a":1,"b":2,"c":3}]

Как я могу вернуть JSON в порядке, определенном в упорядоченном dict?

Редактировать: это не дубликат, потому что связанный пост предназначен только для словаря. Мне нужно, чтобы это работало для списка словарей.

2 ответа

Согласно RFC7159, JavaScript Object Notation (JSON) является текстовым форматом для сериализации структурированных данных. Он получен из объектных литералов JavaScript, как определено в стандарте языка программирования ECMAScript, третье издание [ECMA-262].

Объект является unordered коллекция из нуля или более пар имя / значение, где имя является строкой, а значение - строкой, числом, логическим значением, нулем, объектом или массивом.

Массив является ordered последовательность из нуля или более значений.

Чтобы сделать заказ для вашего JSON вы можете использовать это:

@app.route('/')
def foobar():
    data = OrderedDict([("a",1), ("z",2), ("c",3)])
    return json.dumps([data])

Выход

[{"a": 1, "z": 2, "c": 3}]

Если sort_keys имеет значение true (по умолчанию: False), то выходные словари будут отсортированы по ключу. Для сортировки Вы можете изменить свой код на это:

@app.route('/foobar', methods=['GET'])
def foobar()
    data = [OrderedDict([("a",1),
        ("b",2),
        ("c",3)])]
    return json.dumps(data, sort_keys=True)

Выход

[{"a": 1, "c": 3, "z": 2}]

Ваша проблема в том, что OrderedDict сохраняет порядок вставки для вновь добавленных / измененных пар ключ / значение.

Все зависит от того, как вы получаете ключ / значения в словаре.

Если вы пройдете стандартные **kwargs, вы не сможете.

Если элементы передаются как итеративные (как видно из вашего примера) или вставляются позже, порядок будет сохранен.

Стандартные кварги

d = OrderedDict(a=1, b=2, c=3)
data = [d]
print(json.dumps(data))

Выход:

[{"a": 1, "c": 3, "b": 2}]

Неправильный порядок.

Но с повторяемым

d = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
data = [d]
print(json.dumps(data))

Выход:

[{"a": 1, "b": 2, "c": 3}]

Порядок был сохранен.

Ручная вставка

d = OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
data = [d]
print(json.dumps(data))

Выход:

[{"a": 1, "b": 2, "c": 3}]

И порядок был сохранен снова

Другие вопросы по тегам