Как исправить ошибку 406 (Invalid JSON) при передаче данных из 1С в MongoDB через RESTHeart?

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

При интеграции 1С с MongoDB с использованием RESTHeart разработчики часто сталкиваются с ситуацией, когда попытка записать документ методом PUT или POST завершается ошибкой с кодом HTTP 406 Not Acceptable. Проанализируем, почему возникает эта ошибка, где скрывается проблема при формировании JSON-запроса и как правильно передавать данные без сбоев.

Выясним причину ошибки: анализ лога ответа

В тексте ответа от сервера RESTHeart при ошибке 406 обычно содержатся следующие детали:


{"_exceptions":[{"exception":"org.bson.json.JsonParseException","exception message":"Invalid JSON input. Position: 6. Character: '\ufeff'."}],"http status code":406,"http status description":"Not Acceptable","message":"Invalid JSON"}

Разберем, что означает данный ответ. Символ \ufeff — это маркер последовательности байтов (Byte Order Mark, или BOM). Когда платформа 1С формирует тело запроса с помощью метода УстановитьТелоИзСтроки() без дополнительных параметров, в начало передаваемого UTF-8 потока автоматически вставляется этот служебный символ.

Парсер BSON/JSON на стороне Java-сервиса RESTHeart не ожидает посторонних символов перед открывающей фигурной скобкой {. Получив маркер BOM, сервер отклоняет пакет как некорректный JSON (Invalid JSON) и возвращает статус 406 Not Acceptable.

Способ 1. Отключение символа BOM при формировании HTTPЗапроса

Рассмотрим основной способ решения проблемы на платформе 1С:Предприятие 8.3. Для того чтобы метод УстановитьТелоИзСтроки() не добавлял маркер BOM в начало текстового содержимого, необходимо явно указать третий параметр — ИспользованиеByteOrderMark.НеИспользовать.

Разберем по шагам правильный алгоритм отправки JSON-документа:

  1. Сформируем структуру данных в виде объекта Соответствие или Структура.
  2. Сериализуем данные в строку JSON с помощью объекта ЗаписьJSON.
  3. Установим тело HTTP-запроса с явным отключением метки BOM.
  4. Передадим правильные HTTP-заголовки, включая Content-Type и Accept.

Посмотрим на пример итогового кода 1С:


Соединение = Новый HTTPСоединение("localhost", 8080, "Логин", "Пароль",, 60);

// Заполняем заголовки запроса
ЗаголовокЗапроса = Новый Соответствие;
ЗаголовокЗапроса.Вставить("Content-Type", "application/json; charset=utf-8");
ЗаголовокЗапроса.Вставить("Accept", "application/json");
ЗаголовокЗапроса.Вставить("Authorization", "Basic " + ХэшАвторизации("Логин", "Пароль"));

// Готовим данные для отправки
ИмяФайла = "C:\Data\ObmenMongo\dsfs.png";
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);

СтруктураДокумента = Новый Соответствие;
СтруктураДокумента.Вставить("Base", "1CBase");
СтруктураДокумента.Вставить("Date", ТекущаяДата());
СтруктураДокумента.Вставить("File", Base64Строка(ДвоичныеДанныеФайла));
СтруктураДокумента.Вставить("desc", ИмяФайла);

// Настраиваем параметры записи JSON без переносов строк
ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, СтруктураДокумента);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Создаем запрос и отключаем BOM
ИмяРесурса = "/FileBaseDB/FileTable/" + Документ.Ссылка.УникальныйИдентификатор() + "?id_type=STRING";
HTTPЗапрос = Новый HTTPЗапрос(ИмяРесурса, ЗаголовокЗапроса);

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

ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("txt");
Ответ = Соединение.ВызватьHTTPМетод("PUT", HTTPЗапрос, ИмяФайлаОтвета);

Способ 2. Обходное решение через двоичные данные (для старых версий платформы)

Если разработка ведется на более старых версиях платформы 1С, где метод УстановитьТелоИзСтроки() не поддерживает параметры управления BOM, проанализируем альтернативный вариант. Данные можно перевести в двоичный формат с явным отключением BOM с помощью функции ПолучитьДвоичныеДанныеИзСтроки() и затем передать их через УстановитьТелоИзДвоичныхДанных().

Рассмотрим пример реализации:


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

HTTPЗапрос = Новый HTTPЗапрос(ИмяРесурса, ЗаголовокЗапроса);
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичноеТело);

Ответ = Соединение.ВызватьHTTPМетод("PUT", HTTPЗапрос, ИмяФайлаОтвета);

Способ 3. Передача файлов через GridFS вместо кодирования в Base64

Проанализируем архитектурную особенность хранения файлов в MongoDB. Кодирование файлов в Base64 для передачи внутри стандартного JSON-документа увеличивает размер отправляемых данных примерно на 33% и ограничен максимальным размером BSON-документа (16 МБ).

Для эффективной работы с файлами в RESTHeart встроен модуль GridFS. Вместо упаковки файла в Base64 рекомендуется использовать специальные эндпоинты GridFS, передавая двоичное содержимое файла напрямую в теле запроса методом PUT или POST. Это снимает ограничения по размеру и полностью исключает ошибки, связанные с текстовым парсингом JSON и кодировками.

← На главную