Как избежать экранирования кавычек в JSON при отправке POST-запроса из 1С

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

При интеграции 1С с внешними сайтами и веб-сервисами разработчики часто сталкиваются со следующей проблемой: при отправке POST-запроса, содержащего JSON-строку, принимающая сторона (сервер) получает искаженные данные, в которых все двойные кавычки оказываются экранированными обратным слэшем (например, \"rateId\":\"0\" вместо нормального "rateId":"0"). В результате бэкенд сайта не может корректно распарсить входящий JSON-пакет и возвращает ошибку или пустой результат.

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

Выясняем причину: почему кавычки экранируются?

В процессе обмена данными по протоколу HTTP ключевую роль играет заголовок Content-Type. Именно он сообщает веб-серверу, в каком формате передаются данные в теле запроса и как их нужно обрабатывать. Ошибка экранирования кавычек возникает на стыке двух разных стандартов:

  1. Использование заголовка application/x-www-form-urlencoded. Этот стандарт подразумевает передачу данных в формате «ключ=значение», соединенных амперсандом (например, param1=value1¶m2=value2). Если мы пытаемся передать JSON в виде body={"rateId":"0"} без предварительной подготовки, веб-сервер видит служебные символы URL (кавычки, фигурные скобки, двоеточия). Чтобы обезопасить систему от инъекций и синтаксических ошибок, парсер веб-сервера принудительно экранирует кавычки, превращая их в \".
  2. Переход на заголовок application/json без адаптации сервера. Если мы просто меняем заголовок на application/json, но принимающий скрипт на сайте настроен на чтение стандартного POST-массива (например, глобальной переменной $_POST в PHP), сервер вернет пустой запрос. Это происходит потому, что при отправке JSON данные пишутся напрямую в тело (payload) запроса, а не в переменные формы. Принимающий скрипт не находит ожидаемую переменную и считает запрос пустым.

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

Решение 1. Кодирование JSON-строки (если сервер нельзя изменить)

Если веб-сервер разработан сторонними специалистами и жестко требует передачи данных в формате application/x-www-form-urlencoded с параметром body, нам необходимо выполнить правильное URL-кодирование строки JSON на стороне 1С перед ее отправкой.

Для этого в платформе 1С предусмотрена встроенная функция КодироватьСтроку с использованием системного перечисления СпособКодированияСтроки.КодировкаURL. При таком подходе все небезопасные символы (включая кавычки) заменяются их шестнадцатеричными эквивалентами (например, кавычка превратится в %22), а сервер при получении автоматически декодирует их обратно в нормальный JSON.

Разберем этот процесс на примере кода:


// 1. Создаем защищенное HTTP-соединение
Соединение = Новый HTTPСоединение(
    "api.mysite.net", 
    443, 
    , , , , 
    Новый ЗащищенноеСоединениеOpenSSL()
);

// 2. Указываем заголовки для передачи параметров формы
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

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

СтруктураДанных = Новый Структура; 
СтруктураДанных.Вставить("rateId", "0");
СтруктураДанных.Вставить("email", "ray_honda@mail.ru");
СтруктураДанных.Вставить("phone", "+79111111111");

ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

// 4. КРИТИЧЕСКИ ВАЖНО: Кодируем полученную JSON-строку в формат URL
СтрокаJSON_Закодированная = КодироватьСтроку(СтрокаJSON, СпособКодированияСтроки.КодировкаURL);

// 5. Формируем тело запроса в виде параметр=значение
ТелоЗапроса = "body=" + СтрокаJSON_Закодированная;

// 6. Отправляем запрос на сервер
Запрос = Новый HTTPЗапрос("/order/create", Заголовки);
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Результат = Соединение.ОтправитьДляОбработки(Запрос);

При использовании этого метода на сервер придет валидный URL-запрос, парсер бэкенда автоматически превратит %22 в обычные двойные кавычки, и JSON прочитается без искажений и лишних слэшей.

Решение 2. Переход на чистый application/json (рекомендуемый современный стандарт)

Наиболее правильным решением с точки зрения архитектуры веб-сервисов является передача чистого JSON-пакета непосредственно в теле POST-запроса, минуя промежуточные обертки вроде body=.... Для реализации этого сценария нам потребуется скорректировать логику как в 1С, так и на принимающем веб-сервере.

Шаг 1. Настройка отправки из 1С

В коде 1С мы меняем заголовок Content-Type на application/json и передаем чистую строку JSON в метод УстановитьТелоИзСтроки без каких-либо префиксов:


Соединение = Новый HTTPСоединение("api.mysite.net", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());

// Устанавливаем заголовок контента JSON
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json;charset=utf-8");

// Формируем JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет)); 
// (Заполнение структуры аналогично предыдущему примеру)
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

Запрос = Новый HTTPЗапрос("/order/create", Заголовки);

// Передаем ЧИСТЫЙ JSON в тело запроса. 
// Обязательно отключаем BOM (Byte Order Mark), чтобы у сервера не возникло проблем с парсингом
Запрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Результат = Соединение.ОтправитьДляОбработки(Запрос);

Шаг 2. Настройка приема на стороне веб-сервера

Поскольку данные больше не приходят в виде переменных формы, стандартные инструменты чтения POST-параметров не сработают. Нам нужно прочитать «сырое» тело HTTP-запроса. Рассмотрим, как это сделать на популярных бэкенд-платформах:

Важная техническая деталь: отключение BOM (Byte Order Mark)

Обратите внимание на третий параметр метода УстановитьТелоИзСтроки в коде 1С: мы явно передаем ИспользованиеByteOrderMark.НеИспользовать.

Если этот параметр опустить, 1С по умолчанию запишет в начало текстового потока невидимые спецсимволы разметки кодировки UTF-8 (BOM). Большинство стандартных парсеров JSON на стороне веб-серверов при обнаружении этих символов в начале строки выдают ошибку разбора и полностью отказываются обрабатывать пакет, из-за чего веб-сервис будет возвращать статус 400 (Bad Request) или сообщать о пустом запросе.

Резюме: Чтобы избавиться от экранирования кавычек, всегда соотносите тип передаваемого контента с заголовками HTTP. Если используете application/x-www-form-urlencoded — обязательно применяйте метод КодироватьСтроку. Если проектируете интеграцию с нуля — отдавайте предпочтение отправке «чистого» JSON с заголовком application/json и отключенным BOM.

← На главную