При работе с веб-формами часто возникает необходимость отправить на сервер вложенные структуры данных — объекты и массивы. Однако FormData , предоставляемый браузером, не поддерживает вложенные структуры по умолчанию. Чтобы решить эту задачу, можно использовать рекурсивную функцию, которая преобразует вложенные данн...

Рекурсивная сборка FormData из вложенного объекта в JavaScript

При работе с веб-формами часто возникает необходимость отправить на сервер вложенные структуры данных — объекты и массивы. Однако FormData, предоставляемый браузером, не поддерживает вложенные структуры по умолчанию. Чтобы решить эту задачу, можно использовать рекурсивную функцию, которая преобразует вложенные данные в формат, понятный FormData.

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

Цель

Преобразовать вложенный JavaScript-объект в экземпляр FormData с сохранением структуры через синтаксис квадратных скобок ([]), понятный большинству серверных фреймворков.

Полный листинг функции

buildFormDataRecursively(data, formData = new FormData(), parentKey = '') {
    // Проверка: является ли data объектом (и не файлом)
    if (data && typeof data === 'object' && !(data instanceof File)) {
        if (Array.isArray(data)) {
            // Обработка массива
            data.forEach((value, index) => {
                const key = parentKey ? `${parentKey}[${index}]` : index;
                this.buildFormDataRecursively(value, formData, key);
            });
        } else {
            // Обработка обычного объекта
            for (const key in data) {
                const fullKey = parentKey ? `${parentKey}[${key}]` : key;
                this.buildFormDataRecursively(data[key], formData, fullKey);
            }
        }
    } else {
        // Обработка примитивов и файлов
        const value = data == null ? '' : data;
        formData.append(parentKey, value);
    }

    return formData;
}

Принцип работы

  1. Объекты и массивы обрабатываются рекурсивно: на каждом уровне вложенности ключ формируется с помощью квадратных скобок.
  2. Файлы (File или Blob) и примитивные значения добавляются напрямую.
  3. Null и undefined значения преобразуются в пустую строку.
  4. Функция возвращает экземпляр FormData, готовый к отправке.

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

const data = {
    user: {
        name: 'Alice',
        roles: ['admin', 'editor']
    },
    isActive: true,
    avatar: new File([''], 'avatar.png')
};

const formData = buildFormDataRecursively(data);

В результате formData будет содержать следующие пары ключ-значение:

user[name]       => "Alice"
user[roles][0]   => "admin"
user[roles][1]   => "editor"
isActive         => "true"
avatar           => [File: avatar.png]

Применение на практике

Такая функция особенно полезна при:

  • работе с REST API, где на сервере ожидаются структурированные данные;
  • отправке форм, содержащих вложенные поля и файлы;
  • реализации динамических форм в SPA-фреймворках (React, Vue и др.).

Функция buildFormDataRecursively решает распространённую проблему сериализации вложенных данных для передачи через FormData. Её можно адаптировать под различные требования проекта, включая специальные правила именования ключей, фильтрацию данных или поддержку дополнительных типов.