Поиск несериализуемых значений при помещении в хранилище

В статье разобран пример, как найти несериализуемые значения в случае помещения в хранилище коллекций, содержащих вложенные элементы.
В качестве хранилищ рассмотрены временное хранилище значений и переменные типа ХранилищеЗначения.

Введение

Платформа 8.3.7.1917.

Известно, что в хранилище значений можно поместить только переменные сериализуемого типа. В документации по встроенному языку и в синтакс-помощнике в описании объектов возможность сериализации указывается отметкой «Сериализуется».

При помещении во временное хранилище значений, сериализация которых не поддерживается, возникает ошибка. Текст ошибки зависит от типа переменной. Рассмотрим подробнее каждый из типов.

Хранилище значения

При помещении значения в хранилище конструктором Новый ХранилищеЗначения(<Значение>, <АлгоритмСжатияДанных>) может возникать ошибка «Переданное значение не может быть помещено в ХранилищеЗначения, поскольку не сериализуется или содержит вложенный несериализуемый элемент».

Если в качестве помещаемого значения выступает несериализуемый элемент, то проблем не возникает — мы сразу видим, что он не сериализуется и предпринимаем необходимые действия в зависимости от потребности автоматизации.

Если в качестве помещаемого значения выступает сериализуемая коллекция (например, Структура) с вложенными элементами, то поиск конкретного не сериализуемого значения может принести немало хлопот.

Ниже представлена функция, позволяющая определить, где в коллекциях находятся несериализуемые элементы.

Временное хранилище

При помещении значения во временное хранилище методом ПоместитьВоВременноеХранилище(<Данные>, <Адрес>) может возникать ошибка «Переданное значение не может быть помещено во временное хранилище«.

Здесь казалось бы все по аналогии с хранилищем значения, но возник нюанс: если в качестве данных выступает сериализуемая коллекция с вложенными элементами, сериализация которых не поддерживается, то ошибки не возникает.

Т.е. вот такой код выдает ошибку:

ПоместитьВоВременноеХранилище(Метаданные.Справочники);

А такой — нет:

ПоместитьВоВременноеХранилище(Новый Структура("мдСправочники", Метаданные.Справочники));

Не знаю, это баг или фича, пока отправил письмо на v8 с просьбой признать ошибку. По результатам ответа, пополню статью.

В нижепредставленной функции организована проверка и на помещение во временное хранилище. Т.к. механизм очевидно другой, то реализован специальный параметр, который явно указывает какое хранилище проверяем.

Функции поиска несериалиуемого значения

Их две. Первая — собственно вызов с передачей проверяемого объекта:

// Функция - Получить не сериализуемые объекты
//
// Параметры:
//  Объект     - объект, для которого требуется найти несериализуемые объекты
//  ВариантСериализации  - вариант сериализации при поиске значений. Может принимать значения:
//       "ХранилищеЗначения"  - используется конструктор объекта ХранилищеЗначения
//       "ВременноеХранилище" - используется метод ПоместитьВоВременноеХранилище
//
// Возвращаемое значение:
//  Массив - массив путей до несериализуемых объектов
//
Функция ПолучитьНеСериализуемыеОбъекты(Объект, ВариантСериализации = "ХранилищеЗначения") Экспорт

МассивПутей = Новый Массив();

ДобавитьВМассивПутейНесериализуемыйОбъект(МассивПутей, Объект, ВариантСериализации);

Возврат МассивПутей;

КонецФункции // ПолучитьНеСериализуемыеОбъекты()

Вторая — служебная рекурсия для определения путей несериализуемых объектов:

Процедура ДобавитьВМассивПутейНесериализуемыйОбъект(МассивПутей, Родитель, ВариантСериализации, ПутьКРодителю = "")

Если ТипЗнч(Родитель) = Тип("Массив")
ИЛИ ТипЗнч(Родитель) = Тип("ФиксированныйМассив") Тогда

сч = 0;
Для каждого ЭлементРодителя Из Родитель Цикл
ДобавитьВМассивПутейНесериализуемыйОбъект(МассивПутей, ЭлементРодителя, ВариантСериализации, ПутьКРодителю + "[" + Формат(сч, "ЧН=0; ЧГ=") + "]");
сч = сч + 1;
КонецЦикла;
ИначеЕсли ТипЗнч(Родитель) = Тип("Структура")
ИЛИ ТипЗнч(Родитель) = Тип("Соответствие")
ИЛИ ТипЗнч(Родитель) = Тип("ФиксированнаяСтруктура")
ИЛИ ТипЗнч(Родитель) = Тип("ФиксированноеСоответствие")
Тогда

Для каждого ЭлементРодителя Из Родитель Цикл

ДобавитьВМассивПутейНесериализуемыйОбъект(МассивПутей, ЭлементРодителя.Ключ,     ВариантСериализации, ПутьКРодителю + "/Ключ");
ДобавитьВМассивПутейНесериализуемыйОбъект(МассивПутей, ЭлементРодителя.Значение, ВариантСериализации, ПутьКРодителю + "/" + ЭлементРодителя.Ключ);

КонецЦикла;

Иначе
Попытка

Если ВариантСериализации = "ХранилищеЗначения" Тогда
Результат = Новый ХранилищеЗначения(Родитель);
ИначеЕсли ВариантСериализации = "ВременноеХранилище" Тогда
Адрес = ПоместитьВоВременноеХранилище(Родитель);
УдалитьИзВременногоХранилища(Адрес);
КонецЕсли;

Исключение
МассивПутей.Добавить(ПутьКРодителю);
КонецПопытки;
КонецЕсли;


КонецПроцедуры // ДобавитьВМассивПутейНесериализуемыйОбъект()

2 Comments

  1. dtfmffff

    Долго экспериментировал с сохранением несериализуемых значений между серверными вызовами.

    Спасибо, это работает: ПоместитьВоВременноеХранилище(Новый Структура(«мдСправочники», Метаданные.Справочники));

    Reply
  2. valentinanb

    Спасибо огромное!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *