При разработке интеграций через 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С — это использование встроенной функции РаскодироватьСтроку(). Хотя в старых обсуждениях часто советовали использовать СтрЗаменить() для каждого символа вручную, это крайне неэффективно и чревато ошибками при работе с кириллицей.
Рассмотрим синтаксис функции:
Результат = РаскодироватьСтроку(ИсходнаяСтрока, СпособКодирования, Кодировка)
Разберем по шагам применение этой функции для нашего случая:
СпособКодированияСтроки.URLУпрощенный или СпособКодированияСтроки.URLВКодировкеПоследовательности."UTF-8".Пример кода для декодирования:
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку();
// Убираем имя переменной, если оно есть (например, "orderinfo=")
ЧистаяСтрока = СтрЗаменить(ТелоЗапроса, "orderinfo=", "");
// Декодируем спецсимволы
ДекодированнаяСтрока = РаскодироватьСтроку(ЧистаяСтрока, СпособКодированияСтроки.URLУпрощенный, "UTF-8");
Существует важный нюанс: при передаче данных в формате x-www-form-urlencoded пробелы часто заменяются не на %20, а на знак +. Встроенная функция РаскодироватьСтроку() в некоторых версиях платформы может игнорировать этот момент. Чтобы решение было универсальным, проанализируем ситуацию и добавим дополнительную обработку.
Посмотрим на пример комплексной очистки строки:
Функция ПолноеДекодирование(Знач ИсходнаяСтрока) Экспорт
// Сначала заменяем плюсы на пробелы
Результат = СтрЗаменить(ИсходнаяСтрока, "+", " ");
// Затем выполняем стандартное декодирование %-последовательностей
Результат = РаскодироватьСтроку(Результат, СпособКодированияСтроки.URLУпрощенный);
Возврат Результат;
КонецФункции
Как только мы получили чистую строку, она все еще остается строкой, хотя визуально уже похожа на структуру 1С. Поскольку в примере автора передается JSON, крайне не рекомендуется пытаться достать из него данные методами Лев(), Прав() или СтрНайти(). Правильнее всего использовать объект ЧтениеJSON.
Разберем алгоритм полной обработки входящего POST-запроса:
Процедура ОбработатьЗапрос(Запрос)
// 1. Получаем закодированное тело
ТекстЗапроса = Запрос.ПолучитьТелоКакСтроку();
// 2. Если данные пришли как orderinfo={...}, отсекаем префикс
Если СтрНачинаетсяС(ТекстЗапроса, "orderinfo=") Тогда
ТекстЗапроса = Сред(ТекстЗапроса, СтрДлина("orderinfo=") + 1);
КонецЕсли;
// 3. Декодируем спецсимволы
ЧистыйJSON = РаскодироватьСтроку(ТекстЗапроса, СпособКодированияСтроки.URLУпрощенный);
// 4. Преобразуем JSON в структуру 1С
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ЧистыйJSON);
ДанныеЗаказа = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
// Теперь мы можем обращаться к полям через точку
НомерЗаказа = ДанныеЗаказа.orderNumber;
КонецПроцедуры
Выясним причину, по которой 1С иногда "не видит" параметры автоматически. Платформа заполняет коллекцию ПараметрыЗапроса самостоятельно только если:
Content-Type: application/x-www-form-urlencoded, и веб-сервер (IIS или Apache) корректно передал эти данные платформе.Если вы контролируете сторону отправителя, мы рекомендуем изменить заголовок на Content-Type: application/json и отправлять в теле чистый JSON-объект без префиксов типа orderinfo=. В этом случае в 1С достаточно будет просто прочитать тело, минуя этап РаскодироватьСтроку().
В некоторых случаях, если кодировка входящего потока определена неверно, метод ПолучитьТелоКакСтроку() может вернуть "кракозябры". Чтобы избежать этого, рассмотрим более надежный способ получения данных через двоичный поток:
ДвоичныеДанныеТела = Запрос.ПолучитьТелоКакДвоичныеДанные();
// Явно указываем UTF-8 при чтении из двоичных данных
ТекстТела = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеТела, КодировкаТекста.UTF8);
// Далее применяем РаскодироватьСтроку, как описано выше
Важно понимать, почему использование таблицы ASCII кодов и функции СтрЗаменить() — это плохая практика:
СтрЗаменить() на большом тексте работают значительно медленнее, чем один вызов встроенной функции платформы.%D0%B0. Ручная замена таких связок крайне трудозатратна.Таким образом, всегда отдавайте предпочтение методу РаскодироватьСтроку(), так как он реализован на уровне ядра платформы и учитывает все стандарты кодирования символов.