Flask.request.get json: примеры (PYTHON)

Функция Flask.request.get_json: парсинг JSON данных
Раздел: Веб-фреймворки, HTTP
flask.request.get_json(force: bool=False, silent: bool=False, cache: bool=True): dict or None

Описание функции Flask.request.get_json

Метод request.get_json() в микрофреймворке Flask предназначен для извлечения и парсинга данных в формате JSON из тела входящего HTTP-запроса. Этот метод обычно применяется при обработке запросов от клиентских приложений, REST API или AJAX-запросов, когда данные передаются в теле с заголовком Content-Type: application/json.

Метод выполняет автоматическую десериализацию строки JSON в объекты Python, такие как словари, списки, строки, числа, булевы значения и null, который преобразуется в None.

Аргументы метода

  • force (булевый, необязательный): Если установлен в True, метод пытается парсить тело запроса как JSON, независимо от значения заголовка Content-Type. По умолчанию False.
  • silent (булевый, необязательный): Если установлен в True, при ошибке парсинга метод возвращает None, вместо того чтобы вызвать исключение. По умолчанию False.
  • cache (булевый, необязательный): Определяет, кэшировать ли результат парсинга в объекте запроса. По умолчанию True. Изменение этого параметра может повлиять на производительность.

Возвращаемое значение

Функция возвращает десериализованный объект Python (обычно словарь или список). В случае ошибки парсинга и параметра silent=False возникает исключение BadRequest. Если silent=True, возвращается None.

Базовые примеры использования

Стандартное использование с корректным JSON и заголовком.

from flask import Flask, request

app = Flask(__name__)

@app.route('/api/data', methods=['POST'])
def handle_data():
    data = request.get_json()
    return {'received': data}

При отправке POST-запроса с телом {"name": "John", "age": 30} и заголовком Content-Type: application/json, результат будет:

{
  "received": {
    "name": "John",
    "age": 30
  }
}

Использование параметра force=True для игнорирования заголовка Content-Type.

@app.route('/api/force', methods=['POST'])
def handle_force():
    data = request.get_json(force=True)
    return {'data': data}

Тело запроса: {"key": "value"}. Заголовок Content-Type отсутствует или имеет другое значение. Результат:

{
  "data": {
    "key": "value"
  }
}

Использование параметра silent=True для подавления исключений.

@app.route('/api/silent', methods=['POST'])
def handle_silent():
    data = request.get_json(silent=True)
    if data is None:
        return {'error': 'Invalid JSON'}, 400
    return {'success': True}

При отправке некорректного JSON, например, {name: John} (без кавычек), ответ будет:

{
  "error": "Invalid JSON"
}

Похожие функции и методы в Python

В экосистеме Python для работы с JSON существуют альтернативные способы десериализации.

  • json.loads(): Базовая функция стандартной библиотеки json. Принимает строку JSON и возвращает объект Python. В контексте Flask потребуется предварительно получить сырые данные через request.get_data(as_text=True).
    Пример: data = json.loads(request.get_data(as_text=True)). Используется, когда нужен более низкоуровневый контроль или работа вне Flask.
  • request.json: Это свойство (property), а не метод. Внутри оно вызывает get_json() с параметрами по умолчанию. Его применение удобно для краткости в простых сценариях.
    Пример: data = request.json. Использование get_json() предпочтительнее, когда требуются параметры force или silent.
  • Парсинг данных форм: Для данных типа application/x-www-form-urlencoded или multipart/form-data используются request.form и request.files.

Аналоги функции в других языках программирования

В других языках и фреймворках существуют похожие механизмы для парсинга JSON из тела HTTP-запроса.

JavaScript (Node.js с Express)

const express = require('express');
const app = express();
app.use(express.json()); // middleware для парсинга JSON

app.post('/api/data', (req, res) => {
    const data = req.body; // Данные уже разобраны
    res.json({ received: data });
});

Здесь требуется подключение промежуточного ПО express.json(). Данные становятся доступны в req.body.

PHP

$jsonData = file_get_contents('php://input');
$data = json_decode($jsonData, true); // true для ассоциативного массива
if ($data === null) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON']);
} else {
    echo json_encode(['received' => $data]);
}

В PHP нужно вручную прочитать входной поток и использовать json_decode.

Java (Spring Boot)

@RestController
public class MyController {
    @PostMapping("/api/data")
    public Map handleData(@RequestBody Map payload) {
        // Парсинг выполняется автоматически благодаря аннотации @RequestBody
        Map response = new HashMap<>();
        response.put("received", payload);
        return response;
    }
}

Spring Boot автоматически преобразует тело запроса в объект, указанный в параметре с аннотацией @RequestBody.

Golang (с пакетом net/http и encoding/json)

func handler(w http.ResponseWriter, r *http.Request) {
    var data map[string]interface{}
    err := json.NewDecoder(r.Body).Decode(&data)
    if err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }
    response := map[string]interface{}{"received": data}
    json.NewEncoder(w).Encode(response)
}

В Go используется декодер JSON, работающий непосредственно с потоком тела запроса (r.Body).

Типичные ошибки и их решение

При работе с request.get_json() разработчики часто сталкиваются с рядом характерных ошибок.

Ошибка 1: Отсутствие заголовка Content-Type или его неверное значение.

# Запрос отправлен без заголовка Content-Type: application/json
data = request.get_json() # Вернет None
print(data)
None

Решение: Использовать request.get_json(force=True) или убедиться, что клиент отправляет корректный заголовок.

Ошибка 2: Передача некорректного синтаксиса JSON.

# Тело запроса: { "name": John } (строка John без кавычек)
try:
    data = request.get_json()
except Exception as e:
    print(f"Error: {e}")
Error: 400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 12 (char 11)

Решение: Использовать silent=True для обработки ошибки или валидировать JSON на стороне клиента.

Ошибка 3: Попытка доступа к несуществующим ключам словаря после парсинга.

data = request.get_json()
user_id = data['id'] # KeyError, если ключа 'id' нет

Решение: Использовать метод get (например, data.get('id')) или проверять наличие ключа.

Изменения в последних версиях

Версия Flask 2.3.0 (апрель 2023) внесла значительные изменения в работу с JSON. Была удалена устаревшая собственная реализация парсера JSON в пользу использования стандартного модуля json из стандартной библиотеки Python.

  • Это улучшило производительность и соответствие стандартам.
  • Поведение метода request.get_json() и свойства request.json в большинстве случаев осталось прежним для конечного пользователя, но внутренняя реализация изменилась.
  • Также была улучшена обработка некоторых крайних случаев, связанных с кодировками.

Разработчикам, обновляющимся с очень старых версий, рекомендуется проверить логику работы с нестандартными форматами JSON, так как поведение могло незначительно измениться.

Расширенные примеры использования

Пример 1: Комбинирование параметров force и silent для надежного парсинга.

Пример python
@app.route('/api/robust', methods=['POST', 'PUT'])
def robust_handler():
    # Пытаемся парсить независимо от заголовка и не вызываем исключений
    json_data = request.get_json(force=True, silent=True)
    
    if json_data is None:
        # Логируем ошибку, но отвечаем клиенту понятным сообщением
        app.logger.warning(f"Failed to parse JSON from {request.remote_addr}")
        return {'status': 'error', 'message': 'Invalid or missing JSON data'}, 400
    
    # Валидация структуры данных
    if 'action' not in json_data:
        return {'status': 'error', 'message': "Field 'action' is required"}, 422
    
    # Обработка данных
    return {'status': 'success', 'processed': json_data['action']}

Пример 2: Работа с вложенными структурами и значениями по умолчанию.

Пример python
@app.route('/api/user/preferences', methods=['POST'])
def update_preferences():
    data = request.get_json()
    if not data:
        return {'error': 'No data'}, 400
    
    # Безопасное извлечение вложенных данных
    theme = data.get('preferences', {}).get('theme', 'light')
    notifications = data.get('preferences', {}).get('notifications', True)
    
    # Обновление настроек пользователя в БД (заглушка)
    # user.update_preferences(theme=theme, notifications=notifications)
    
    return {
        'updated': {
            'theme': theme,
            'notifications': notifications
        }
    }

Пример 3: Отключение кэширования для потоковой обработки или отладки.

Пример python
@app.route('/api/debug', methods=['POST'])
def debug_handler():
    # Первый вызов с отключенным кэшем
    data1 = request.get_json(cache=False)
    # Второй вызов вынудит снова прочитать и разобрать тело запроса
    data2 = request.get_json(cache=False)
    
    # Это может быть полезно, если между вызовами тело запроса было модифицировано
    # или для оценки производительности парсинга
    return {
        'first_parse': data1,
        'second_parse': data2,
        'are_equal': data1 == data2
    }

Пример 4: Использование с пользовательскими классами десериализатора (через наследование).

Пример python
from flask import Flask, Request
import json

class CustomJSONRequest(Request):
    def get_json(self, force=False, silent=False, cache=True):
        # Вызов родительского метода
        rv = super().get_json(force=force, silent=silent, cache=cache)
        # Дополнительная кастомная логика
        if isinstance(rv, dict):
            rv['_parsed_by'] = 'CustomJSONRequest'
        return rv

app = Flask(__name__)
app.request_class = CustomJSONRequest

@app.route('/api/custom')
def custom_handler():
    data = request.get_json(force=True)
    return data

При отправке { "test": 1 } ответ будет содержать добавленное поле:

{
  "test": 1,
  "_parsed_by": "CustomJSONRequest"
}

питон flask.request.get_json function comments

En
Flask.request.get json Parse incoming JSON request data