Почему axios отправляет пустой объект вместо map?
Я использую React и axios. Пытаюсь отправлять запрос:
/* Здесь создаётся объект axios */
const apiRequester = axios.create({
baseURL: 'http://localhost:8080/',
withCredentials: true
});
/* Данный метод должен отправить запрос */
const saveOpenParagraphs = (id, paragraphsToSave) => {
console.log(paragraphsToSave)
return apiRequester.post('programs/' + id + '/open-paragraphs', paragraphsToSave, {
headers: {
'X-XSRF-TOKEN': getXSRFToken()
}
});
}
/* Не имеет прямого отношения к вопросу, но мало ли, вдруг как-то влияет */
const getXSRFToken = () => {
return Cookies.get('XSRF-TOKEN');
}
Объект paragraphsToSave это карта, мапа. Вот как она выглядит в консоли (логируется непосредственно перед отправкой запроса):
Map(22) {100007 => 400, 100015 => 900, 100016 => 1000, 100017 => 1100, 100018 => 1200, …}
[[Entries]]
0: {100007 => 400}
1: {100015 => 900}
2: {100016 => 1000}
3: {100017 => 1100}
4: {100018 => 1200}
5: {100019 => 1300}
6: {100020 => 1400}
7: {100021 => 1500}
8: {100022 => 1600}
9: {100023 => 1700}
10: {100024 => 1800}
11: {100027 => 2100}
12: {100028 => 2200}
13: {100029 => 2300}
14: {100030 => 2400}
15: {100031 => 2500}
16: {100032 => 2600}
17: {100033 => 2700}
18: {100035 => 2800}
19: {100036 => 3000}
20: {100037 => 3100}
21: {100038 => 3200}
size: (...)
__proto__: Map
Во кладке network тело запроса выглядит так:
{}
Почему такое происходит? Остальные объекты отправляются нормально (раньше карту не отправлял), а здесь тело запроса пустое. Как исправить?
Ответы (2 шт):
Почему axios отправляет пустой объект вместо map?
А с чего бы axios'у поступать иначе? (риторический вопрос)
Если посмотреть в документацию этой библиотеки - то можно заметить, что там вполне однозначно перечислены допустимые типы значений:
datais the data to be sent as the request body
Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
When notransformRequestis set, must be of one of the following types:
- string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
- Browser only: FormData, File, Blob
- Node only: Stream, Buffer
То есть, о поддержке Map не заявлено.
Зато упомянута возможность использования свойства конфигурации transformRequest, которое служит для модификации данных запроса передаваемых в методы axios. Описание данного свойства находится выше по тексту той же самой страницы документации. Если вкратце: оно принимает массив коллбэков, которые будут вызываться (с двумя аргументами - тело запроса, объект заголовков) перед отправкой запроса, и последний из коллбэков должен вернуть окончательное значение тела запроса в одном из поддерживаемых библиотекой типов (string | Buffer | ArrayBuffer | FormData | Stream).
Как исправить?
Обычным для опенсорсного продукта путем: форкнуть репозиторий проекта ➝ реализовать в библиотеке поддержку значений типа Map ➝ убедиться в соблюдении всех рекомендаций/требований руководства для соавторов ➝ отправить авторам PR.
Из ответа @yar85 стало понятно, что надо каким-то образом привести объект Map к string, потому что карту в чистом виде axios не воспринимает.
Моё решение оказалось очень простым, хотя оно, вероятно, не является оптимальным. Но у меня простая карта, где в качестве ключа и значения выступают примитивы, поэтому мне такое решение подошло:
JSON.stringify(Object.fromEntries(paragraphsToSave))
Первая функция Object.fromEntries вернула карту в виде простого объекта:
{100007: 400, 100015: 900, ...}
А JSON.stringify вернул из объекта строку.
Вы можете подробнее прочитать про различные способы преобразования объекта Map в строку в следующих источниках: ссылка, ссылка, ссылка.