При интеграции 1С с внешними веб-сервисами, отправке HTTP-запросов или получении ответов API разработчики часто сталкиваются с ситуацией, когда текстовые данные возвращаются в кодированном виде. Вместо привычного кириллического текста мы видим последовательности символов вида \u041d\u043e\u0432\u043e\u0435. Это так называемые Unicode escape-последовательности. Для отправки запросов и анализа ответов веб-сервисов можно использовать инструмент для тестирования REST API в 1С.
Стандартные механизмы платформы, такие как функция РаскодироватьСтроку(), рассчитаны на декодирование URL-формата (процентное кодирование вида %D0%9D) и не умеют напрямую обрабатывать формат \uXXXX. В этой статье мы подробно разберем несколько способов декодирования таких строк в 1С: от современных встроенных средств до универсальных алгоритмов "в лоб" для старых версий платформы.
---
Если вы работаете на современной версии платформы 1С:Предприятие, вам не нужно вручную разбирать строку по символам. Формат \uXXXX является стандартом де-факто для сериализации строк в JSON. Мы можем использовать встроенный в платформу быстрый парсер JSON, чтобы раскодировать строку буквально в несколько строчек кода.
Давайте проанализируем, как это сделать. Мы можем обернуть нашу закодированную строку в формат JSON-массива (заключив её в квадратные скобки и кавычки) и прочитать с помощью встроенного объекта ЧтениеJSON.
Рассмотрим пример кода:
// Функция декодирует Unicode escape-последовательности через парсер JSON
Функция РаскодироватьСтрокуЧерезJSON(ИсходнаяСтрока) Экспорт
// Формируем валидный JSON-массив, содержащий одну строку
JSONСтрока = "[""" + ИсходнаяСтрока + """]";
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(JSONСтрока);
Попытка
РезультатМассив = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Возвращаем первый и единственный элемент массива, который автоматически раскодировался
Возврат РезультатМассив[0];
Исключение
ЧтениеJSON.Закрыть();
// В случае ошибки парсинга возвращаем исходную строку
ЗаписьЖурналаРегистрации("ДекодированиеСтроки", УровеньЖурналаРегистрации.Предупреждение,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат ИсходнаяСтрока;
КонецПопытки;
КонецФункции
Преимущества этого подхода:
---
Если перед вами стоит задача реализовать декодирование на старых версиях платформ (например, 1С 8.2, 8.1 или даже 7.7), где встроенного объекта ПрочитатьJSON ещё не существовало, нам придется написать собственный парсер.
Давайте разберем по шагам логику ручного декодирования:
\u, то считываем следующие 4 символа (это шестнадцатеричный код символа).Символ().\u не встречен, мы просто переносим текущий символ в выходную строку без изменений. Это позволяет корректно обрабатывать смешанные строки, где латиница, знаки препинания и кириллица идут вперемешку (например: /Вывод изображения \u0441\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u043e\u0439.mht).Ниже представлен оптимизированный и исправленный вариант функции ручного декодирования:
Функция УТФвСтроку(ВхСтр) Экспорт
ВыхСтр = "";
поз = 1;
ДлинаСтроки = СтрДлина(ВхСтр);
Пока поз <= ДлинаСтроки Цикл
симв = Сред(ВхСтр, поз, 1);
// Проверяем наличие маркера \u
Если симв = "\" И (поз + 5 <= ДлинаСтроки) И Сред(ВхСтр, поз + 1, 1) = "u" Тогда
ВыхКод = 0;
Вес = 4096; // 16 в кубе для первого разряда четырехзначного hex-числа
// Начинаем разбор 4-х шестнадцатеричных символов, идущих после \u
Для инд = 1 По 4 Цикл
кодСимв = КодСимвола(Сред(ВхСтр, поз + 1 + инд, 1));
// Переводим символ шестнадцатеричной системы в числовое значение
Если кодСимв > 96 Тогда // Диапазон a-f (строчные)
кодСимв = кодСимв - 87;
ИначеЕсли кодСимв > 64 Тогда // Диапазон A-F (прописные)
кодСимв = кодСимв - 55;
Иначе // Диапазон 0-9
кодСимв = кодСимв - 48;
КонецЕсли;
ВыхКод = ВыхКод + кодСимв * Вес;
Вес = Вес / 16;
КонецЦикла;
// Добавляем раскодированный символ к результату
ВыхСтр = ВыхСтр + Символ(ВыхКод);
// Сдвигаем указатель позиции на длину всей конструкции \uXXXX (6 символов)
поз = поз + 6;
Иначе
// Обычные символы переносим "как есть"
ВыхСтр = ВыхСтр + симв;
поз = поз + 1;
КонецЕсли;
КонецЦикла;
Возврат ВыхСтр;
КонецФункции
Важное замечание по исправлению ошибок исходного кода с форумов: во многих старых публикациях встречается ошибка в инкременте позиции указателя (писали поз = поз + 4 вместо поз = поз + 6 после успешного декодирования). Это приводило к "съеданию" последующих символов текста или к бесконечным циклам. В представленном выше алгоритме эта ошибка полностью исправлена.
---
Если ручной перебор символов кажется вам медленным на больших текстах в старых конфигурациях, можно прибегнуть к помощи операционной системы Windows. Мы можем использовать встроенный движок JScript через системный COM-объект htmlfile. Метод основан на использовании стандартной JavaScript-функции unescape(), предварительно заменив вхождение \u на символ процента с буквой u (%u).
Рассмотрим, как реализовать этот подход:
Функция ДекодироватьЧерезHTMLFile(ИсходнаяСтрока) Экспорт
// Подготавливаем строку: unescape понимает формат %uXXXX
ПодготовленнаяСтрока = СтрЗаменить(ИсходнаяСтрока, "\u", "%u");
Попытка
HTMLДокумент = Новый COMОбъект("htmlfile");
HTMLДокумент.open("text/html");
HTMLДокумент.write("<script>document.write(unescape('" + ПодготовленнаяСтрока + "'));</script>");
HTMLДокумент.close();
РаскодированнаяСтрока = HTMLДокумент.documentElement.outerText;
Возврат РаскодированнаяСтрока;
Исключение
// Если COM-объекты заблокированы политиками безопасности ОС, возвращаем исходную строку
Возврат ИсходнаяСтрока;
КонецПопытки;
КонецФункции
Этот метод работает быстрее ручного перебора на платформе 1С v7.7 или 8.1 при обработке объемных файлов, однако он зависит от операционной среды выполнения (не будет работать на серверах под управлением Linux). Автоматизацию переноса данных между окнами систем в таких случаях берет на себя платформа программных роботов One RPA.
---
Мы проанализировали три кардинально отличающихся подхода к решению проблемы декодирования строк. При выборе метода рекомендуем руководствоваться следующими правилами: