При интеграции 1С с внешними системами (через Web-API, HTTP-сервисы или при чтении текстовых файлов) разработчики часто сталкиваются со строками, в которых кириллические символы заменены на escape-последовательности Unicode. Например, вместо понятного текста «а-2 б-2 в-4» в переменной содержится строка вида \u0430-2 \u0431-2 \u0432-4.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем решения, предложенные участниками форума, а также рассмотрим более производительные и современные способы декодирования таких строк в платформе 1С:Предприятие 8.3.
Участники обсуждения на форуме обратили внимание, что прямая запись закодированной строки через объект ЗаписьJSON приводит к повторному экранированию символов (обратный слэш удваивается, превращаясь в \\uXXXX). В результате на выходе получается та же самая недекодированная строка.
Чтобы заставить платформу корректно проанализировать и декодировать спецсимволы, было предложено «обмануть» парсер: искусственно преобразовать исходную плоскую строку в полноценный JSON-объект (структуру с ключом и значением) с помощью строковой конкатенации, а затем прочитать этот объект штатными средствами 1С.
Проанализируем алгоритм этого решения по шагам:
{"Строка": "значение"}.ЧтениеJSON и передаем ему полученную строку.ПрочитатьJSON, который автоматически преобразует escape-последовательности Юникода в нормальные символы кириллицы.Посмотрим на пример реализации данного подхода:
ИсходнаяСтрока = "\u0430-2 \u0431-2 \u0432-4";
// Искусственно формируем структуру JSON-объекта
СтрокаJSON = "{""Строка"":""" + ИсходнаяСтрока + """}";
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаJSON);
// Получаем объект Соответствие или Структуру с декодированным значением
РезультатОбъект = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
// Извлекаем наше значение
ДекодированнаяСтрока = РезультатОбъект["Строка"];
Сообщить(ДекодированнаяСтрока); // В окне сообщений выведется: а-2 б-2 в-4
Этот метод полностью рабочий, однако он имеет недостаток: избыточность. Для декодирования одной текстовой переменной нам приходится инициализировать в оперативной памяти объект типа Структура или Соответствие, что снижает общую производительность кода.
Разберем распространенное заблуждение, прозвучавшее на форуме: утверждение о том, что «1С ничего не знает про таблицу символов Юникод». Начиная с версии 8.3.6, платформа нативно поддерживает стандарт RFC 4627 и великолепно декодирует любые последовательности вида \uXXXX.
Согласно спецификации формата JSON, валидным документом может выступать не только объект (в фигурных скобках) или массив (в квадратных скобках), но и обычный JSON-примитив. В частности — простая строка, заключенная в двойные кавычки.
Это означает, что нам не нужно создавать сложные структуры. Достаточно просто добавить к нашей закодированной строке двойные кавычки по бокам и прочитать её напрямую через ПрочитатьJSON. Выясним, насколько лаконичнее становится наш код:
ИсходнаяСтрока = "\u0430-2 \u0431-2 \u0432-4";
// Оборачиваем строку в двойные кавычки, чтобы превратить её в валидный примитив JSON
СтрокаJSON = """" + ИсходнаяСтрока + """";
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаJSON);
// Читаем напрямую в строковую переменную
Результат = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
Сообщить(Результат); // Результат: а-2 б-2 в-4
Преимущества этого подхода:
Если вы пишете код в любой современной типовой конфигурации 1С (ERP, Управление торговлей, Бухгалтерия предприятия, ЗУП и др.), то в вашем распоряжении имеется Библиотека Стандартных Подсистем (БСП). В БСП уже встроены готовые функции-обертки, которые позволяют избавиться от ручного создания объектов ЧтениеJSON.
В зависимости от версии БСП в вашей системе, вы можете использовать готовые служебные методы общего назначения. Например:
УправлениеКонтактнойИнформациейСлужебный.СтрокуJSONВСтруктуру(Значение)РаботаВМоделиСервисаБТС.СтруктураИзСтрокиJSON(Строка)ОбщегоНазначенияДокументооборот.ЗначениеИзСтрокиJSON(СтрокаJSON)Под капотом эти функции используют те же механизмы чтения JSON-структур, но избавляют вас от написания шаблонного кода.
Рассмотрим ситуации, когда разработка ведется на старых версиях платформы (например, 1С 8.2 или ранних релизах 8.3), где встроенный объект ЧтениеJSON отсутствует. В этом случае мы можем применить два альтернативных метода декодирования.
Напишем собственную функцию разбора строки. Суть алгоритма: находим в строке вхождения спецсимвола \u, извлекаем идущие следом 4 шестнадцатеричных символа (Hex-код), переводим их в десятичную систему счисления (Dec) и восстанавливаем символ встроенной функцией Символ().
Посмотрим на программную реализацию:
Функция ДекодироватьЮникод(Знач ВходнаяСтрока) Экспорт
Результат = "";
Поз = Найти(ВходнаяСтрока, "\u");
Пока Поз > 0 Цикл
// Добавляем текст, который шел до спецсимвола
Результат = Результат + Лев(ВходнаяСтрока, Поз - 1);
// Извлекаем 4 символа шестнадцатеричного кода
КодHex = Сред(ВходнаяСтрока, Поз + 2, 4);
// Переводим Hex в десятичное число
КодDec = HexToDec(КодHex);
// Преобразуем число в символ и добавляем в результат
Результат = Результат + Символ(КодDec);
// Отрезаем обработанную часть строки
ВходнаяСтрока = Сред(ВходнаяСтрока, Поз + 6);
Поз = Найти(ВходнаяСтрока, "\u");
КонецЦикла;
Результат = Результат + ВходнаяСтрока;
Возврат Результат;
КонецФункции
Функция HexToDec(Знач ЗначениеHex)
СимволыHex = "0123456789ABCDEF";
ЗначениеHex = ВРег(ЗначениеHex);
Результат = 0;
Для Индекс = 1 По СтрДлина(ЗначениеHex) Цикл
СимволHex = Сред(ЗначениеHex, Индекс, 1);
Поз = Найти(СимволыHex, СимволHex) - 1;
Результат = Результат * 16 + Поз;
КонецЦикла;
Возврат Результат;
КонецФункции
Данный вариант полностью универсален, работает на любой версии платформы (включая 1С 7.7) и не зависит от операционной системы.
Если код выполняется в среде операционной системы Windows, можно задействовать COM-объект MSScriptControl.ScriptControl с языком JavaScript, который нативно умеет обрабатывать кодировку Unicode.
Разберем этот простой пример:
// Инициализируем COM-объект
JS = Новый COMОбъект("MSScriptControl.ScriptControl");
JS.Language = "JScript";
ИсходнаяСтрока = "\u0430-2 \u0431-2 \u0432-4";
// Передаем строку в JS движок для мгновенного декодирования
ДекодированнаяСтрока = JS.Eval("'" + ИсходнаяСтрока + "'");
Сообщить(ДекодированнаяСтрока); // Результат: а-2 б-2 в-4
Важное ограничение: этот способ привязан к операционной системе Windows и не будет работать на серверах под управлением Linux. Также могут возникнуть проблемы совместимости при работе в 64-битных рабочих процессах сервера 1С.
Мы проанализировали несколько подходов к решению проблемы декодирования Unicode-символов. Для современных конфигураций 1С самым быстрым, лаконичным и надежным является Способ 2 (Декодирование через примитив JSON), так как он использует эффективный встроенный парсер платформы и не требует создания лишних объектов в памяти.