Как распарсить и декодировать строку со спецсимволами в 1С при получении HTTP-запроса?

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

При разработке интеграций через HTTP-сервисы в 1С программисты часто сталкиваются с ситуацией, когда данные в теле POST-запроса приходят в "закодированном" виде. Например, вместо привычных кавычек или скобок мы видим последовательности символов типа %22, %7B или %3A. Это стандартное поведение для передачи данных по протоколу HTTP, известное как URL Encoding. В этой статье мы подробно разберем, как правильно преобразовывать такие строки в читаемый формат и извлекать из них полезную информацию.

Почему параметры запроса оказываются "зашифрованы"?

Когда сайт или внешняя система отправляет данные на ваш HTTP-сервис 1С с заголовком Content-Type: application/x-www-form-urlencoded, все спецсимволы заменяются на их шестнадцатеричные коды ASCII, предваряемые знаком процента. Это делается для того, чтобы технические символы URL не конфликтовали с данными пользователя. Рассмотрим ситуацию, когда Запрос.ПараметрыЗапроса оказывается пустым, и нам приходится использовать метод Запрос.ПолучитьТелоКакСтроку(). В результате мы получаем нечто подобное:

orderinfo=%7B%22orderNumber%22%3A3074%7D

Проанализируем эту строку: %7B — это открывающая фигурная скобка, %22 — кавычка, а %3A — двоеточие. Наша задача — превратить это в валидный JSON-объект.

Способ 1: Использование встроенной функции РаскодироватьСтроку

Самый правильный и надежный метод в современной платформе 1С — это использование встроенной функции РаскодироватьСтроку(). Хотя в старых обсуждениях часто советовали использовать СтрЗаменить() для каждого символа вручную, это крайне неэффективно и чревато ошибками при работе с кириллицей.

Рассмотрим синтаксис функции:

Результат = РаскодироватьСтроку(ИсходнаяСтрока, СпособКодирования, Кодировка)

Разберем по шагам применение этой функции для нашего случая:

  1. Исходная строка: Это наше тело запроса.
  2. Способ кодирования: Для стандартных веб-запросов следует использовать СпособКодированияСтроки.URLУпрощенный или СпособКодированияСтроки.URLВКодировкеПоследовательности.
  3. Кодировка: Чаще всего это "UTF-8".

Пример кода для декодирования:


ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
// Убираем имя переменной, если оно есть (например, "orderinfo=")
ЧистаяСтрока = СтрЗаменить(ТелоЗапроса, "orderinfo=", "");
// Декодируем спецсимволы
ДекодированнаяСтрока = РаскодироватьСтроку(ЧистаяСтрока, СпособКодированияСтроки.URLУпрощенный, "UTF-8");

Способ 2: Обработка специфики "application/x-www-form-urlencoded" и знака плюс

Существует важный нюанс: при передаче данных в формате x-www-form-urlencoded пробелы часто заменяются не на %20, а на знак +. Встроенная функция РаскодироватьСтроку() в некоторых версиях платформы может игнорировать этот момент. Чтобы решение было универсальным, проанализируем ситуацию и добавим дополнительную обработку.

Посмотрим на пример комплексной очистки строки:


Функция ПолноеДекодирование(Знач ИсходнаяСтрока) Экспорт
    // Сначала заменяем плюсы на пробелы
    Результат = СтрЗаменить(ИсходнаяСтрока, "+", " ");
    // Затем выполняем стандартное декодирование %-последовательностей
    Результат = РаскодироватьСтроку(Результат, СпособКодированияСтроки.URLУпрощенный);
    Возврат Результат;
КонецФункции

Способ 3: Парсинг JSON после декодирования

Как только мы получили чистую строку, она все еще остается строкой, хотя визуально уже похожа на структуру 1С. Поскольку в примере автора передается JSON, крайне не рекомендуется пытаться достать из него данные методами Лев(), Прав() или СтрНайти(). Правильнее всего использовать объект ЧтениеJSON.

Разберем алгоритм полной обработки входящего POST-запроса:


Процедура ОбработатьЗапрос(Запрос)
    // 1. Получаем закодированное тело
    ТекстЗапроса = Запрос.ПолучитьТелоКакСтроку();
    
    // 2. Если данные пришли как orderinfo={...}, отсекаем префикс
    Если СтрНачинаетсяС(ТекстЗапроса, "orderinfo=") Тогда
        ТекстЗапроса = Сред(ТекстЗапроса, СтрДлина("orderinfo=") + 1);
    КонецЕсли;
    
    // 3. Декодируем спецсимволы
    ЧистыйJSON = РаскодироватьСтроку(ТекстЗапроса, СпособКодированияСтроки.URLУпрощенный);
    
    // 4. Преобразуем JSON в структуру 1С
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ЧистыйJSON);
    ДанныеЗаказа = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    
    // Теперь мы можем обращаться к полям через точку
    НомерЗаказа = ДанныеЗаказа.orderNumber;
КонецПроцедуры

Почему параметры не попали в стандартную коллекцию Запрос.ПараметрыЗапроса?

Выясним причину, по которой 1С иногда "не видит" параметры автоматически. Платформа заполняет коллекцию ПараметрыЗапроса самостоятельно только если:

Если вы контролируете сторону отправителя, мы рекомендуем изменить заголовок на Content-Type: application/json и отправлять в теле чистый JSON-объект без префиксов типа orderinfo=. В этом случае в 1С достаточно будет просто прочитать тело, минуя этап РаскодироватьСтроку().

Работа с двоичными данными для надежности

В некоторых случаях, если кодировка входящего потока определена неверно, метод ПолучитьТелоКакСтроку() может вернуть "кракозябры". Чтобы избежать этого, рассмотрим более надежный способ получения данных через двоичный поток:


ДвоичныеДанныеТела = Запрос.ПолучитьТелоКакДвоичныеДанные();
// Явно указываем UTF-8 при чтении из двоичных данных
ТекстТела = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеТела, КодировкаТекста.UTF8);
// Далее применяем РаскодироватьСтроку, как описано выше

Ограничения ручной замены через СтрЗаменить()

Важно понимать, почему использование таблицы ASCII кодов и функции СтрЗаменить() — это плохая практика:

Таким образом, всегда отдавайте предпочтение методу РаскодироватьСтроку(), так как он реализован на уровне ядра платформы и учитывает все стандарты кодирования символов.

← На главную