Почему при отправке JSON из 1С возникает ошибка 400 Invalid JSON request и как убрать BOM?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции платформы 1С с внешними веб-сервисами и REST API разработчики часто сталкиваются с ситуацией, когда запрос, успешно работавший в версии 1С:Предприятие 8.2 или при проверке сторонними утилитами, в 1С:Предприятие 8.3 возвращает ошибку 400 Bad Request со следующим текстом:

{"status":400,"error":"Invalid JSON request","message":"unexpected character at line 1, column 1"}

При этом сам текст документа полностью валиден и не содержит синтаксических ошибок. Разберем по шагам, почему возникает эта ошибка и какими способами можно правильно передать строку JSON без маркера последовательности байтов.

Анализируем причину сбоя

Обратим внимание на диагностическое сообщение веб-сервиса: парсер ожидает увидеть открывающую фигурную { или квадратную [ скобку, однако спотыкается на первом символе первой строки. Если сопоставить длину отправляемого пакета (заголовок Content-Length), можно заметить разницу ровно в 3 байта.

Причина такого поведения — добавление невидимой трехбайтовой сигнатуры UTF-8 Byte Order Mark (BOM: 0xEF, 0xBB, 0xBF) в самое начало тела запроса. Стандарт RFC 8259, определяющий формат JSON, запрещает наличие маркера BOM в начале потока данных. Большинство современных веб-серверов строго следуют этому правилу и отсекают запросы с маркером еще на этапе первичного синтаксического анализа.

Выясним причину появления BOM в 1С. В оперативной памяти строка, полученная через объект ЗаписьJSON, BOM не содержит. Сигнатура появляется в тот момент, когда мы помещаем сформированный текст в объект HTTPЗапрос. Метод HTTPЗапрос.УстановитьТелоИзСтроки() по умолчанию может автоматически добавлять маркер BOM для кодировки UTF-8 в зависимости от установленного режима совместимости конфигурации.

Способ 1. Явное отключение BOM при установке тела запроса

Рассмотрим самый простой, чистый и производительный вариант. Нам не требуется сохранять данные во временные файлы или очищать строку регулярными выражениями. Достаточно использовать штатные параметры платформы 1С:


// Формируем JSON в строку средствами платформы
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Формируем HTTP-запрос
HTTPЗапрос = Новый HTTPЗапрос("/api/v3/endpoint/");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

// Явно указываем ИспользованиеByteOrderMark.НеИспользовать
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

// Отправляем запрос через существующее HTTPСоединение
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

Обратите внимание на третий параметр метода HTTPЗапрос.УстановитьТелоИзСтроки() — системное перечисление ИспользованиеByteOrderMark.НеИспользовать. Оно гарантирует, что строка попадет в сетевой сокет в чистом виде без стартовых трех байт.

Способ 2. Передача данных через двоичные данные

Если в алгоритме требуется контролировать байтовое представление полезной нагрузки до отправки или использовать единые функции формирования запросов, разберем способ с преобразованием строки в двоичные данные без сигнатуры:


// Преобразуем строку в двоичные данные без добавления BOM
ЗаписатьBOM = Ложь;
ДвоичныеДанныеТела = ПолучитьДвоичныеДанныеИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ЗаписатьBOM);

// Устанавливаем двоичные данные напрямую в запрос
HTTPЗапрос = Новый HTTPЗапрос("/api/v3/endpoint/");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТела);

В методе ПолучитьДвоичныеДанныеИзСтроки() третий параметр принимает булево значение. Передавая Ложь, мы исключаем автоматическую вставку BOM.

Способ 3. Работа с объектом ЗаписьJSON через файл

Если сериализация объекта занимает значительный объем памяти и требуется прямая запись во временный файл на диске, обратимся к параметрам метода ОткрытьФайл() объекта ЗаписьJSON:


ИмяФайла = ПолучитьИмяВременногоФайла("json");

ЗаписьJSON = Новый ЗаписьJSON;
// Третий параметр метода отвечает за добавление BOM
ЗаписьJSON.ОткрытьФайл(ИмяФайла, "UTF-8", Ложь);
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
ЗаписьJSON.Закрыть();

HTTPЗапрос = Новый HTTPЗапрос("/api/v3/endpoint/");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзИмениФайла(ИмяФайла);

HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
УдалитьФайлы(ИмяФайла);

Параметр Ложь при открытии файла гарантирует запись содержимого строго без маркера UTF-8 BOM.

Подводные камни и частые ошибки

Посмотрим на распространенные нюансы, с которыми можно столкнуться при решении данной проблемы:

  1. Использование объекта ЗаписьТекста по имени файла: конструктор вида Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8) не имеет флага отключения маркера BOM. Платформа 1С при создании файла на диске таким способом всегда добавляет маркер BOM в начало файла.
  2. Псевдоним кодировки CESU-8: среди разработчиков популярен лайфхак с указанием кодировки "CESU-8", так как для нее платформа 1С не ставит BOM. Однако этот метод опасен: кодировка CESU-8 отличается от UTF-8 при обработке символов за пределами базовой многоязыковой плоскости (например, эмодзи или специфические пиктограммы кодируются суррогатными парами). Это приведет к нарушению стандарта UTF-8 и ошибке парсинга на удаленном сервере. Рекомендуется всегда использовать КодировкаТекста.UTF8 с явным отключением BOM.
← На главную