Почему при выгрузке из 1С в Битрикс тело запроса искажается и приходит в виде сериализованной строки?

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

При настройке интеграции между 1С:Предприятие и веб-сайтами на платформе 1С-Битрикс (или любыми другими PHP-бэкендами) разработчики часто сталкиваются с ситуацией, когда отправленный JSON-запрос воспринимается сервером некорректно. В отладчике 1С мы видим правильную JSON-строку, но техническая поддержка со стороны сайта утверждает, что к ним приходят «непонятные символы», например, строки, начинающиеся с a:1:{...}. Также часто возникает путаница с тем, что аналогичный запрос из программы Postman проходит успешно, а из 1С — нет.

В этой статье мы подробно разберем причины такого поведения, проанализируем разницу в формировании HTTP-запросов и рассмотрим правильный алгоритм отправки данных в формате JSON из 1С.

Анализ симптомов: что означает a:1:{...}

Прежде чем переходить к коду, давайте разберемся, что именно видит принимающая сторона. Если разработчики Битрикса говорят, что тело запроса изменилось и показывают строку вида a:1:{...}, это важная диагностическая информация.

Данный префикс — это результат работы стандартной функции PHP serialize(). Это означает, что:

  1. Сервер получил запрос.
  2. Сервер попытался интерпретировать данные.
  3. Механизм логирования на сайте сохранил данные не в исходном «сыром» виде, а предварительно пропустив их через сериализацию PHP массива.

Это наводит нас на мысль, что проблема не в том, что 1С «ломает» данные по пути, а в том, как именно веб-сервер интерпретирует входящий поток байт. Часто принимающая сторона ожидает JSON, но из-за отсутствия метаданных пытается разобрать его как параметры обычной веб-формы, что и приводит к некорректному формированию массива данных на входе PHP-скрипта.

Гипотеза 1: Лишние символы и BOM (Byte Order Mark)

Первое, на что стоит обратить внимание при формировании тела запроса из строки — это кодировка и наличие метки порядка байтов (BOM). Стандарт JSON (RFC 8259) не рекомендует использовать BOM, и многие парсеры могут выдавать ошибку синтаксиса, если строка начинается с невидимых символов EF BB BF.

В платформе 1С метод УстановитьТелоИзСтроки объекта HTTPЗапрос позволяет явно управлять этим параметром. Давайте посмотрим, как гарантированно отправить «чистый» UTF-8 без BOM. Это считается хорошей практикой (best practice) при любых HTTP-обменах.


// Создаем тело запроса в формате JSON
СтрокаJSON = "{\"product\": \"item1\", \"amount\": 100}";

// Создаем объект запроса
ЗапросHTTP = Новый HTTPЗапрос("/api/endpoint");

// Явно указываем кодировку UTF-8 и отключаем использование BOM
ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаJSON, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);

Использование ИспользованиеByteOrderMark.НеИспользовать гарантирует, что в начало потока не будут добавлены лишние байты. Однако, как показывает практика, одного этого действия часто недостаточно. Если сервер продолжает видеть данные как «кашу» или пустой массив, проблема лежит глубже — в заголовках запроса.

Гипотеза 2: Отсутствие заголовков Content-Type

Это самая распространенная причина, по которой запросы из Postman работают, а из 1С — нет. Давайте разберем механику процесса.

Когда вы используете Postman и выбираете тип тела Raw -> JSON, программа «умная»: она автоматически добавляет к вашему запросу HTTP-заголовок:

Content-Type: application/json

Платформа 1С работает на более низком уровне. Объект HTTPЗапрос — это чистый лист. Если вы положили в тело запроса JSON-строку, но не сказали серверу, что это JSON, сервер (особенно на базе PHP/Apache/Nginx) по умолчанию будет считать, что вы отправляете данные обычной HTML-формы (формат application/x-www-form-urlencoded).

Что происходит на сервере Битрикс без заголовка:

  1. PHP получает поток данных.
  2. Видит отсутствие Content-Type: application/json.
  3. Пытается разобрать JSON-строку {"a":1} как набор параметров вида key=value.
  4. Так как формат не совпадает, массив $_POST формируется некорректно (либо пустой, либо ключ — это вся строка целиком).
  5. При попытке залогировать этот некорректный массив через serialize(), получается структура a:1:{...}, которую и видят разработчики сайта.

Решение проблемы

Для корректной передачи данных необходимо явно указать серверу тип передаваемого контента. В 1С это делается через коллекцию заголовков объекта HTTPЗапрос. Рассмотрим полный, рабочий пример кода, который решает проблему искажения данных.


// 1. Подготовка данных (сериализация в JSON средствами 1С)
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ДанныеДляОтправки = Новый Структура("Sum, Comment", "100.00", "Оплата заказа");
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();

// 2. Создание запроса
Ресурс = "/rest/api/order/add";
ЗапросHTTP = Новый HTTPЗапрос(Ресурс);

// 3. ВАЖНО: Установка заголовков
// Сообщаем серверу, что отправляем именно JSON
ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/json"); 

// Также хорошим тоном является указание желаемой кодировки в заголовке, 
// хотя application/json по стандарту подразумевает UTF-8
ЗапросHTTP.Заголовки.Вставить("Charset", "UTF-8");

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

// 5. Отправка
Соединение = Новый HTTPСоединение("example.com", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL);
Попытка
    Ответ = Соединение.ОтправитьДляОбработки(ЗапросHTTP);
    // Обработка ответа...
Исключение
    Сообщить("Ошибка отправки: " + ОписаниеОшибки());
КонецПопытки;

Почему разработчики говорят про "отсутствие сериализации"?

В переписке часто возникает недопонимание терминов. Фраза «1С не сериализует данные» технически неверна, если вы уже сформировали JSON-строку. 1С прекрасно сериализует объекты в строку JSON с помощью объекта ЗаписьJSON.

Когда разработчики Битрикса говорят подобное, они обычно имеют в виду, что их внутренние методы (например, Context::getCurrent()->getRequest()->getJsonList()) не отрабатывают автоматически. Эти методы внутри себя проверяют наличие заголовка Content-Type: application/json. Если заголовка нет, метод считает, что данных нет, или они не в том формате, и возвращает пустоту или ошибку. То есть проблема не в структуре данных (сериализации), а в метаданных запроса (заголовках), позволяющих эти данные правильно прочитать.

Резюме и чек-лист для проверки

Если при интеграции вы столкнулись с ситуацией, когда сервер не видит ваши данные или видит их искаженными:

  1. Проверьте заголовки. Это причина №1. Убедитесь, что строка Заголовки.Вставить("Content-Type", "application/json"); присутствует в коде.
  2. Исключите BOM. Используйте третий параметр в методе УстановитьТелоИзСтроки со значением ИспользованиеByteOrderMark.НеИспользовать.
  3. Сравните с Postman. Если в Postman работает, откройте там консоль (View -> Show Postman Console) и посмотрите вкладку Request Headers. Вы увидите все заголовки, которые Postman подставил скрыто от вас. Перенесите недостающие (особенно Content-Type и Authorization) в код 1С.
  4. Используйте прокси. Для глубокой диагностики можно пустить трафик 1С через Fiddler или Charles (указав их как прокси в HTTPСоединение). Это позволит увидеть байт-в-байт, что именно уходит из 1С.
← На главную