Возврат JSON-ответа из представления Flask
У меня есть функция, которая анализирует CSV-файл с помощью библиотеки Pandas и возвращает словарь с краткой информацией. Я хочу вернуть результаты в ответе из представления Flask. Как правильно вернуть ответ в формате JSON?
Пример кода:
@app.route("/summary")
def summary():
d = make_summary()
# вернуть результат в формате JSON
Какой подход следует использовать для отправки данных в формате JSON из функции представления?
5 ответ(ов)
jsonify сериализует данные, которые вы передаете ему, в формат JSON. Если вы хотите сериализовать данные самостоятельно, выполните аналогичные действия, которые делает jsonify, создав ответ с status=200 и mimetype='application/json'.
Вот пример кода:
from flask import json
@app.route('/summary')
def summary():
data = make_summary() # Ваши данные для сериализации
response = app.response_class(
response=json.dumps(data), # Сериализация данных в JSON
status=200, # Статус ответа
mimetype='application/json' # MIME тип
)
return response
В этом примере make_summary() генерирует данные, которые вы хотите вернуть, а json.dumps(data) преобразует их в строку JSON. Затем вы создаете экземпляр response_class, передавая сериализованные данные, статус и MIME-тип.
Если по каким-то причинам вы не хотите использовать jsonify, вы можете сделать то, что он делает, вручную. Вызовите flask.json.dumps, чтобы создать данные в формате JSON, затем верните ответ с заголовком контента application/json.
from flask import json
@app.route('/summary')
def summary():
data = make_summary()
response = app.response_class(
response=json.dumps(data),
mimetype='application/json'
)
return response
Обратите внимание, что flask.json отличается от встроенного модуля json. Он будет использовать более быстрый модуль simplejson, если он доступен, и позволяет интегрировать различные функции с вашим приложением Flask.
В Flask версии 1.1.x поддерживается возможность возвращать JSON-словарь без необходимости вызова jsonify. Однако, если вы хотите вернуть что-то, отличное от словаря, вам все равно нужно использовать jsonify.
Вот пример:
@app.route("/")
def index():
return {
"api_stuff": "values",
}
Этот код эквивалентен следующему:
@app.route("/")
def index():
return jsonify({
"api_stuff": "values",
})
Если вам интересно узнать больше, можете ознакомиться с запросом на добавление этой функции: https://github.com/pallets/flask/pull/3111.
В вашем коде используется декоратор return_json, который оборачивает результаты функции и преобразует их в формат JSON с помощью jsonify. Это действительно делает код более читабельным, особенно когда у вас несколько условных ветвей возврата.
Однако стоит отметить, что ваш декоратор не поддерживает возвращение кортежа, например, в формате (content, status). В вашем случае, если вам нужно возвращать ошибки с соответствующими статусами, вы решили использовать app.errorhandler, что является допустимым подходом.
Вот как это работает:
- Декоратор
return_jsonпринимает функциюf, оборачивает её и вызывает, передавая все ключевые аргументы (kwargs). - Результат выполнения функции
fпередается вjsonify, что всегда будет возвращать JSON ответ.
Вы можете улучшить обработку различных типов возврата, если будет нужна такая функциональность. Например, если необходимо возвращать не только данные, но и статус, можно комбинировать логику внутри декоратора.
Вот пример, как это можно сделать:
import functools
from flask import jsonify
def return_json(f):
@functools.wraps(f)
def inner(*args, **kwargs):
result = f(*args, **kwargs)
if isinstance(result, tuple):
return jsonify(result[0]), result[1]
return jsonify(result)
return inner
@app.route('/test/<arg>')
@return_json
def test(arg):
if arg == 'list':
return [1, 2, 3], 200
elif arg == 'dict':
return {'a': 1, 'b': 2}, 200
elif arg == 'bool':
return True, 200
return 'none of them', 404
Теперь ваш декоратор поддерживает возврат кортежей, что позволяет указывать как содержимое ответа, так и HTTP статус. Это может быть удобнее при обработки ошибок и различных статусов ответа.
В версиях Flask до 0.11 функция jsonify не позволяла возвращать массив напрямую. Вместо этого вам необходимо передать список в качестве аргумента с именем.
Правильный пример будет выглядеть следующим образом:
@app.route('/get_records')
def get_records():
results = [
{
"rec_create_date": "12 Jun 2016",
"rec_dietary_info": "nothing",
"rec_dob": "01 Apr 1988",
"rec_first_name": "New",
"rec_last_name": "Guy",
},
{
"rec_create_date": "1 Apr 2016",
"rec_dietary_info": "Nut allergy",
"rec_dob": "01 Feb 1988",
"rec_first_name": "Old",
"rec_last_name": "Guy",
},
]
return jsonify(results=results)
Обратите внимание, что вместо list нужно использовать переменную results, содержащую ваши данные.
Почему Python не может разобрать эти данные JSON? [закрыто]
Как отправить JSON-данные с помощью Python Requests?
Ошибка JSONDecodeError: Ожидалось значение: строка 1, столбец 1 (символ 0)
Преобразование строки даты JSON в datetime в Python
Отключение кэширования в Flask