Сделал на Flask декоратор, который должен принимать JSON-строку из html form.
@app.route('/processjson', methods=['POST'])
data = request.get_json(force=True)
return jsonify(data)
Через Постман проверил POST запросом, отправив JSON-строку. Все работает. Однако, отправляя саму форму из клиента, получаю:
400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)
Получается, form генерирует неверный формат.
Вот form:
<form action="/processjson" enctype="application/json" method="post">
<input type="hidden" name="name" value="Bender">
<input type="submit" value="TEST">
</form>
request.headers['Content-Type'] возвращает 'application/x-www-form-urlencoded'
Задача состоит в том, что я должен получать из form JSON-строку, а после неких операций отправлять JSON-строку в ту же форму.
Браузерные формы не поддерживают application/json. И, похоже, никогда не будут поддерживать:
Осторожно! Эта спецификация не поддерживается, и HTML Working Group не хочет поддерживать её в будущем.
Можно отправлять запросы с application/json джаваскриптом. В самых простейших key/value случаях можно просто пройтись по FormData и собрать все ключики в объект, который потом закодировать в json и отправить:
document.getElementById('benderform').addEventListener('submit', submitForm);
function submitForm(event) {
// Отменяем стандартное поведение браузера с отправкой формы
event.preventDefault();
// event.target — это HTML-элемент form
let formData = new FormData(event.target);
// Собираем данные формы в объект
let obj = {};
formData.forEach((value, key) => obj[key] = value);
// Собираем запрос к серверу
let request = new Request(event.target.action, {
method: 'POST',
body: JSON.stringify(obj),
headers: {
'Content-Type': 'application/json',
},
});
// Отправляем (асинхронно!)
fetch(request).then(
function(response) {
// Запрос успешно выполнен
console.log(response);
// return response.json() и так далее см. документацию
},
function(error) {
// Запрос не получилось отправить
console.error(error);
}
);
// Код после fetch выполнится ПЕРЕД получением ответа
// на запрос, потому что запрос выполняется асинхронно,
// отдельно от основного кода
console.log('Запрос отправляется');
}
<form action="/processjson" id="benderform">
<input type="hidden" name="name" value="Bender">
<input type="submit" value="TEST">
</form>
(Конечно, в реальности всё должно выглядеть не так топорно, как в этом примере (и вообще этот пример не работает, потому что в сниппетах Stack Overflow не предусмотрено тестирование ajax-запросов), но направление для дальнейших действий я дал.)
Документация: FormData, Fetch, async/await, XMLHttpRequest (если нужна поддержка старых браузеров)
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости