Возврат 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
, содержащую ваши данные.
Как обойти "datetime.datetime не сериализуем в JSON"?
Почему Python не может разобрать эти данные JSON? [закрыто]
Как записать данные JSON в файл?
Как сделать класс сериализуемым в JSON
Как отправить JSON-данные с помощью Python Requests?