Как я могу сохранить порядок 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}]
И порядок был сохранен снова