В процессе разработки часто возникает задача временного сохранения состояния прикладного объекта (документа или справочника) в файл. Это может потребоваться для создания резервных копий перед сложными манипуляциями, передачи данных между базами или реализации механизма «черновиков». В этой статье мы подробно разберем, как правильно реализовать сохранение и восстановление объектов, избегая типичных ошибок со ссылками.
Первая и самая важная деталь, которую мы должны усвоить: методы сохранения данных работают по-разному в зависимости от того, что мы им передаем. Если передать методу ЗначениеВФайл или любому сериализатору ссылку (ДокументСсылка), система сохранит только уникальный идентификатор (GUID) документа. При попытке восстановления мы получим ту же самую ссылку на тот же самый документ в базе, но никакие изменения, сделанные в памяти, не сохранятся.
Для того чтобы сохранить текущее состояние данных (реквизиты, табличные части), мы должны работать с типом Объект (например, ДокументОбъект или СправочникОбъект). Проанализируем, какими способами это можно сделать.
Это классический и наиболее универсальный метод. Он позволяет превратить объект в текстовый формат, который легко прочитать или передать. Разберем по шагам, как реализовать сохранение объекта в строку XML и его последующее чтение.
Сохранение объекта в XML:
// Предположим, у нас есть переменная ДокументОбъект, полученная через ПолучитьОбъект()
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(); // Будем сохранять в строку для наглядности
// Записываем объект. НазначениеТипаXML.Явное помогает избежать проблем при десериализации
ЗаписатьXML(ЗаписьXML, ДокументОбъект, НазначениеТипаXML.Явное);
ТекстXML = ЗаписьXML.Закрыть();
// Теперь переменную ТекстXML можно сохранить в текстовый файл через ТекстовыйДокумент
Восстановление объекта из XML:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ТекстXML);
// Метод ПрочитатьXML создает НОВЫЙ экземпляр объекта в памяти
НовыйОбъект = ПрочитатьXML(ЧтениеXML);
// Важно: объект находится в памяти. Чтобы он попал в базу, нужно вызвать:
// НовыйОбъект.Записать();
Рассмотрим более современный подход, доступный в платформе 8.3. Формат JSON компактнее, чем XML, и работает быстрее. Для этого мы будем использовать СериализаторXDTO.
Этот метод удобен тем, что он автоматически обрабатывает структуру объекта 1С, включая все его вложенные части.
Пример записи в JSON:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
// Используем глобальный контекст СериализаторXDTO
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, ДокументОбъект, НазначениеТипаXML.Явное);
ТекстJSON = ЗаписьJSON.Закрыть();
При восстановлении через СериализаторXDTO.ПрочитатьJSON мы получим готовый объект, с которым можно работать так же, как и в случае с XML.
Выясним причину популярности и опасности встроенных методов 1С. Методы ЗначениеВФайл и ЗначениеВСтрокуВнутр сохраняют данные во внутреннем формате системы (похожем на структуру в фигурных скобках).
Важные нюансы:
ДокументОбъект.ЗначениеВСтрокуВнутр завязан на внутренние идентификаторы метаданных. Если вы переименуете реквизит в конфигураторе или удалите его, старые файлы могут перестать читаться корректно.Проанализируем ситуацию, когда нам нужно сохранить состояние объекта не во внешнем файле, а прямо внутри информационной базы (например, в регистре сведений). Для этого идеально подходит объект ХранилищеЗначения.
// Сохраняем объект в хранилище (оно автоматически сжимает данные)
Хранилище = Новый ХранилищеЗначения(ДокументОбъект, Новый СжатиеДанных(9));
// Теперь это хранилище можно записать в реквизит с типом "ХранилищеЗначения"
// Извлечение:
ВосстановленныйОбъект = Хранилище.Получить();
Посмотрим на технические ограничения. На тонком клиенте мы не можем напрямую работать с файловой системой так же свободно, как на сервере.
Правильный алгоритм работы будет следующим:
ПоместитьВоВременноеХранилище().ПолучитьФайл(), чтобы предложить пользователю сохранить документ на его компьютер.Если наш документ содержит десятки тысяч строк в табличных частях, обычный XML может стать слишком тяжелым. В этом случае мы рекомендуем использовать формат FastInfoset (бинарный XML). Чтобы его задействовать, при открытии файла для записи нужно указать соответствующий параметр:
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, , , , Истина);
Это позволит значительно уменьшить размер файла и ускорить процесс сериализации.
Мы рассмотрели основные способы программной работы с состоянием объектов. Для большинства задач сериализация через XML или JSON является самым надежным и гибким решением. Главное — всегда помнить, что для сохранения данных нужно оперировать Объектом, а после восстановления — не забывать вызывать метод Записать(), если данные должны физически обновиться в базе данных.