При разработке в среде 1С:Предприятие 8.3 часто возникает задача сохранения сложных данных (например, структуры, соответствия или массива) в один текстовый реквизит. Особенно остро этот вопрос встает при адаптации типовых конфигураций (например, 1С:УНФ, 1С:БП или 1С:КА) через механизм расширений, когда мы ограничены в возможности добавлять новые реквизиты в таблицы базы данных. В таких случаях программисты часто используют "халявные" текстовые поля неограниченной длины (например, поле Содержание в табличной части запасов или товаров), упаковывая туда целый набор пользовательских колонок.
В этой статье мы подробно разберем, какими инструментами в современной платформе 1С 8.3 принято пользоваться для укладывания структуры в бесконечную строку и последующего извлечения данных, почему старый метод ЗначениеВСтрокуВнутр() больше не актуален и как реализовать этот процесс без лишних обращений к серверу.
Исторически в системе 1С:Предприятие существовал простой метод ЗначениеВСтрокуВнутр() (и парный ему ЗначениеИзСтрокиВнутр()). Он позволял сериализовать практически любой объект базы данных или коллекции в системную строку. Однако в современной разработке использовать его крайне не рекомендуется по следующим причинам:
Рассмотрим современные альтернативные методы, которые позволяют решить задачу быстро, безопасно и эффективно.
Использование формата JSON — это современный стандарт для работы с коллекциями данных в 1С. Главное преимущество данного подхода заключается в том, что сериализация и десериализация JSON полностью поддерживаются на стороне клиента (в тонком и веб-клиентах). Это позволяет мгновенно упаковывать данные интерактивных колонок при изменении строк табличной части без единого серверного вызова, сохраняя высокую отзывчивость интерфейса.
Проанализируем два варианта реализации этого метода в зависимости от версии вашей платформы.
Вариант А: Для платформы 1С:Предприятие 8.3.23 и выше
Если ваша конфигурация работает на современной версии платформы, вам доступны новые сверхкомпактные глобальные методы. Они позволяют выполнить преобразование буквально в одну строку кода без ручного создания вспомогательных объектов чтения и записи.
Код для упаковки структуры в строку на клиенте:
// Формируем структуру с данными колонок
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("СкидкаПроцент", 15);
СтруктураДанных.Вставить("СпецУсловие", Истина);
СтруктураДанных.Вставить("КомментарийМенеджера", "Срочная доставка");
// Укладываем структуру в строку JSON одним методом
СтрокаРеквизита = ЗаписатьЗначениеJSON(СтруктураДанных);
Код для распаковки строки обратно в структуру:
// Восстанавливаем структуру из сохраненной строки
Если Не ПустаяСтрока(СтрокаРеквизита) Тогда
СтруктураДанных = ПрочитатьЗначениеJSON(СтрокаРеквизита);
// Теперь мы можем обратиться к свойствам: СтруктураДанных.СкидкаПроцент
КонецЕсли;
Вариант Б: Для версий платформы от 8.3.6 до 8.3.22
Если вы работаете на более ранних релизах платформы 1С 8.3, то для работы с JSON потребуется классический синтаксис с использованием специализированных объектов ЗаписьJSON и ЧтениеJSON.
Код для упаковки структуры на клиенте:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
// Записываем структуру в поток JSON
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
// Получаем итоговую строку
СтрокаРеквизита = ЗаписьJSON.Закрыть();
Код для распаковки структуры на клиенте:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаРеквизита);
// Считываем структуру из потока
СтруктураДанных = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Этот способ работает невероятно быстро, не нагружает сеть и серверные процессоры, а также гарантирует, что данные будут сохранены в стандартном кроссплатформенном формате. Для валидации входящей структуры пригодится обработка для проверки заполненности обязательных полей в строке JSON.
Еще один рабочий способ заключается в оборачивании нашей структуры в объект ХранилищеЗначения с последующим его преобразованием в XML-строку. Этот метод часто используется разработчиками "по старой памяти", но он имеет один существенный недостаток.
Важное ограничение: Конструктор объекта ХранилищеЗначения доступно только на сервере. Это означает, что при каждом изменении данных в строке табличной части вам придется выполнять вызов сервера (даже если он будет безконтекстным). При медленном интернет-соединении или высокой нагрузке на сервер это приведет к заметным "микрофризам" интерфейса для конечного пользователя.
Давайте посмотрим на программную реализацию этого метода. Код упаковки структуры на сервере:
&НаСервереБезКонтекста
Функция УпаковатьСтруктуруВСтроку(Знач СтруктураДанных) Экспорт
// Помещаем структуру в ХранилищеЗначения
Хранилище = Новый ХранилищеЗначения(СтруктураДанных);
// Сериализуем хранилище в строку XML
Возврат XMLСтрока(Хранилище);
КонецФункции
Код восстановления структуры из XML-строки на сервере:
&НаСервереБезКонтекста
Функция РаспаковатьСтруктуруИзСтроки(Знач СтрокаXML) Экспорт
Если ПустаяСтрока(СтрокаXML) Тогда
Возврат Новый Структура;
КонецЕсли;
// Восстанавливаем ХранилищеЗначения из XML-строки
Хранилище = XMLЗначение(Тип("ХранилищеЗначения"), СтрокаXML);
// Извлекаем саму структуру
Возврат Хранилище.Получить();
КонецФункции
Этот способ надежен с точки зрения сохранения сложных типов данных 1С (которые JSON может не поддерживать напрямую, например, ссылки на элементы справочников или перечисления), но платой за эту универсальность становится необходимость постоянных обращений к серверу. Для отслеживания таких ссылок в сериализованных данных подойдёт подсистема для поддержки ссылочной целостности в реквизитах типа ХранилищеЗначений.
Если вы ведете разработку в типовой конфигурации (например, УНФ, ERP или Бухгалтерия), то в вашем распоряжении уже есть Библиотека Стандартных Подсистем (БСП). Разработчики БСП предусмотрели готовые общие модули для сериализации данных, чтобы избавить вас от необходимости писать вспомогательный код вручную.
Для быстрого сворачивания структуры вы можете использовать функции серверных общих модулей общего назначения:
// Сериализация структуры силами БСП
СтрокаРеквизита = ОбщегоНазначения.ЗначениеВСтрокуJSON(СтруктураДанных);
// Обратная десериализация силами БСП
СтруктураДанных = ОбщегоНазначения.ЗначениеИзСтрокиJSON(СтрокаРеквизита);
Обратите внимание, что данные вызовы выполняются на сервере. Если вам критически важно выполнять весь цикл операций строго на клиенте (без серверных вызовов в формах документов), отдавайте предпочтение встроенным средствам платформы, описанным в Решении №1.
Выяснив сильные и слабые стороны каждого подхода, мы можем составить простую рекомендацию: