При интеграции 1С с внешними системами через HTTP-сервисы разработчики часто сталкиваются с ситуацией, когда отправленный JSON-пакет приходит в базу в «искаженном» виде. Вместо аккуратной структуры мы получаем строку, где все пробелы заменены на знаки «плюс» (+), а в самом начале строки добавляется странный префикс (например, text= или data=). В результате стандартный метод десериализации JSON выдает ошибку, и прочитать данные не удается.
В этой статье мы подробно разберем, почему возникает такое поведение, как правильно настроить отправку данных на стороне клиента и что делать на стороне 1С, если формат отправки изменить невозможно.
Описанные симптомы однозначно указывают на то, что отправляющая сторона (клиент) передает данные с заголовком Content-Type: application/x-www-form-urlencoded вместо стандартного application/json.
Формат application/x-www-form-urlencoded — это стандартный способ кодирования данных HTML-форм при отправке POST-запросов. По спецификации этого формата:
text. Из-за этого в начале строки и появляется префикс text=.+).%22, а фигурная скобка — в %7B).Когда мы вызываем метод Запрос.ПолучитьТелоКакСтроку(), платформа 1С возвращает нам «сырое» тело POST-запроса в том виде, в котором оно пришло от клиента. Если клиент закодировал данные как форму, мы и получаем закодированную строку.
Проанализируем два способа решения этой проблемы: правильный (настройка клиента) и обходной (обработка внутри 1С).
Самый правильный и архитектурно верный способ решить проблему — заставить отправляющую систему передавать JSON в «чистом» виде без лишнего кодирования. Если вы сами настраиваете интеграцию (например, тестируете запросы в Postman) или можете повлиять на сторонних разработчиков, выполните следующие действия:
Content-Type: application/json.При такой настройке тело запроса придет в 1С в исходном виде, и мы сможем обработать его без лишних манипуляций:
// В HTTP-сервисе 1С при правильном Content-Type:
СтрокаJSON = Запрос.ПолучитьТелоКакСтроку("UTF-8");
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
СтруктураЗапроса = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Если отправителем выступает другая база 1С, убедитесь, что при формировании запроса вы явно задаете заголовок и передаете JSON напрямую в тело:
HTTPЗапрос = Новый HTTPЗапрос("/hs/MyService/v1/data");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);
Бывают ситуации, когда веб-сервис принимает запросы от сторонней системы (например, платежного шлюза, мессенджера или CRM), логику работы которой изменить невозможно. Если интеграция жестко требует отправки в формате application/x-www-form-urlencoded, нам придется корректно разбирать такое тело запроса на стороне 1С.
Простая замена плюсов через СтрЗаменить(СтрокаЗапроса, "+", "%20") и ручное отсечение префикса — рабочий вариант, но он ненадежен. Что если имя параметра изменится или в запросе придет несколько полей? Рассмотрим универсальный и безопасный алгоритм разбора входящих urlencoded-данных.
Создадим вспомогательную функцию, которая преобразует сырое тело запроса в удобную структуру (или соответствие) параметров:
// Функция разбирает тело x-www-form-urlencoded в соответствие параметров
Функция РазобратьТелоFormUrlEncoded(Знач ТелоСтрокой) Экспорт
Результат = Новый Соответствие;
// Шаг 1. Согласно стандарту urlencoded, пробелы кодируются как "+".
// Заменяем их на "%20", чтобы встроенная функция РаскодироватьСтроку отработала корректно.
// Настоящие символы "+" к этому моменту уже закодированы отправителем в "%2B", поэтому они не пострадают.
ТелоСтрокой = СтрЗаменить(ТелоСтрокой, "+", "%20");
// Шаг 2. Разделяем параметры, если их передается несколько (разделитель "&")
МассивПар = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ТелоСтрокой, "&");
Для Каждого Параметр Из МассивПар Цикл
ПозицияРавно = Найти(Параметр, "=");
Если ПозицияРавно > 0 Тогда
// Выделяем имя ключа и его значение
КлючЗакодированный = Лев(Параметр, ПозицияРавно - 1);
ЗначениеЗакодированное = Прав(Параметр, СтрДлина(Параметр) - ПозицияРавно);
// Шаг 3. Декодируем ключ и значение из URL-формата
Ключ = РаскодироватьСтроку(КлючЗакодированный, СпособКодированияСтроки.КодировкаURL, "UTF-8");
Значение = РаскодироватьСтроку(ЗначениеЗакодированное, СпособКодированияСтроки.КодировкаURL, "UTF-8");
Результат.Вставить(Ключ, Значение);
Иначе
// Параметр без значения
Ключ = РаскодироватьСтроку(Параметр, СпособКодированияСтроки.КодировкаURL, "UTF-8");
Результат.Вставить(Ключ, "");
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Теперь применим разработанную функцию в обработчике нашего HTTP-сервиса. Мы извлечем закодированное тело, превратим его в соответствие параметров, получим нужный JSON по ключу и успешно его распарсим:
// Обработчик метода POST HTTP-сервиса
Функция ШаблонМетодаPOST(Запрос)
// Всегда явно указываем кодировку UTF-8 при чтении тела запроса
ТелоСтрокой = Запрос.ПолучитьТелоКакСтроку("UTF-8");
// Парсим параметры формы
ПараметрыФормы = РазобратьТелоFormUrlEncoded(ТелоСтрокой);
// Ищем наш JSON, отправленный в параметре "text"
СтрокаJSON = ПараметрыФормы.Получить("text");
Если СтрокаJSON = Неопределено Тогда
// Если параметр не найден, попробуем прочитать тело напрямую (вдруг клиент исправили)
СтрокаJSON = ТелоСтрокой;
КонецЕсли;
// Пытаемся прочитать JSON
Попытка
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
СтруктураЗапроса = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Здесь выполняем основную бизнес-логику с полученной структурой...
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки("Данные успешно обработаны", КодировкаТекста.UTF8);
Возврат Ответ;
Исключение
// Обработка ошибки парсинга JSON
Ответ = Новый HTTPСервисОтвет(400);
Ответ.УстановитьТелоИзСтроки("Ошибка декодирования JSON: " + ОписаниеОшибки(), КодировкаТекста.UTF8);
Возврат Ответ;
КонецПопытки;
КонецФункции
При обмене данными по протоколу HTTP крайне важно следить за кодировками. Обратите внимание на следующие моменты:
ПолучитьТелоКакСтроку() всегда указывайте кодировку (обычно "UTF-8"). Если этого не сделать, платформа попытается определить кодировку по системным настройкам или заголовкам, что часто приводит к появлению «кракозябр» вместо кириллицы.РаскодироватьСтроку также принимает третьим параметром кодировку. Всегда используйте "UTF-8" для соответствия современным стандартам веб-разработки.multipart/form-data (этот формат обычно используется для отправки файлов), ручной разбор строки через замену символов не поможет. Для этого в платформе 1С предусмотрены специальные объекты семейства ЧтениеMIME.Таким образом, мы детально разобрали особенности обработки входящих POST-запросов. Понимание стандартов кодирования веб-данных позволяет легко устранять подобные технические сложности и создавать надежные интеграционные механизмы.