Перейти к содержанию

IStorageSerializer и его реализация StorageSerializer

IStorageSerializer и его реализация StorageSerializer

IStorageSerializer — это интерфейс, представляющий действия для сериализации и десериализации объектов с учетом контента, выгружаемого во внешние файлы.

Сериализация объекта

Для сериализации объекта необходимо передать в метод сам объект сериализации, а также, опционально, параметры сериализации реализующие интерфейс IStorageSerializationOptions. Эти параметры включают в себя:

Список мэппингов IList<IStorageMapping>, которые представляют собой root-путь до подобъекта внутри storage и список опций сериализации (IList<IStorageContentMapping>) для отдельно взятых контентов.

IStorageContentMapping в свою очередь содержит информацию о storage-пути, по которому находится выгружаемый контент, имени файла в который этот контент выгружается и флаг для особой логики генерации хэш-части этого файла.

Пример кода сериализации карточки:

// Карточка, которую хотим сериализовать. CardStoreRequest storeRequest = AnyMethodToGetCardStoreRequest(); IList storage = new List<object> { storeRequest.GetStorage() };

// Мэппинги для строковой секции KrSecondaryProcesses var cardStorageFileMappings = new List<IStorageContentMapping> { new StorageContentMapping( "Sections.KrSecondaryProcesses.Fields.VisibilitySourceCondition", // storage-путь до контента "VisibilitySourceCondition.cs"), // имя выгружаемого файла new StorageContentMapping( "Sections.KrSecondaryProcesses.Fields.VisibilitySqlCondition", "VisibilitySqlCondition.sql") };

// Мэппинги для коллекционной секции "KrStages" var rowsCount = storeRequest.Card.Sections["KrStages"].Rows.Count; for (int i = 0; i < rowsCount; i++) { cardStorageFileMappings.Add(new StorageContentMapping( $"Sections.KrStages.Rows[{i}].RuntimeSourceCondition", "RuntimeSourceCondition.cs", "RowID")); // если задан данный параметр, то при вычислении хэш-части имени выгружаемого файла, будет использовано поле с указанным ключем, например "RowID" cardStorageFileMappings.Add(new StorageContentMapping( $"Sections.KrStages.Rows[{i}].RuntimeSqlCondition", "RuntimeSqlCondition.txt", "RowID")); }

// Создаем опции сериализации var serializationOptions = new StorageSerializationOptions() { StorageMappings = new List<IStorageMapping> { new StorageMapping() { StorageRootPath = "[0].Card", // root-путь до подобъекта внутри storage StoragePathFileMappings = cardStorageFileMappings } } };

// Получаем сериализованный json основной карточки, в котором вместо контента будут записаны имена файлов // и коллекцию кортежей с именами файлов и контентом, которые в последствии можно записать во внешние хранилища и/или применить любую другую логику (string json, IEnumerable<(string fileName, object content)> contents) = await this.storageSerializer.SerializeAsync(storage, serializationOptions, cancellationToken) .ConfigureAwait(false);

Десериализация объекта

Для десериализации объекта необходимо передать в метод строку, содержащую сериализованный объект, функцию, которая будет возвращать поток с контентом на основании строкового параметра (Func<string, Stream>) а также, опционально, имя базовой папки, относительно которой находится контент.

В случае десериализации карточек, вышеописанная функция, получающая контент, в качестве параметра получает полный путь ко внешнему файлу с контентом, это наименование складывается в конвертере (JsonTypedConverter) из имени базовой папки + имя файла.

Т.е. данная функция может выглядеть, например, так:

private static Stream GetFileContentStream(string filePath) { FileStream fileStream = new(filePath, FileMode.Open); return fileStream; }

Пример кода десериализации карточки:

// Получаем сериализованную json-строку, например из потока string json; using (var reader = new StreamReader( sourceStream, // FileStream с сериализованной карточкой Encoding.UTF8, true, FileHelper.DefaultFileBufferSize, leaveOpen: true)) { json = await reader.ReadToEndAsync(); }

// Путь до папки с контентом (в нашем случае находится в подпапке с самой карточкой, имя этой подпапки равно имя файла карточки без расширения) var contentDirectoryName = Path.Combine( Path.GetDirectoryName(sourcePath) ?? string.Empty, Path.GetFileNameWithoutExtension(sourcePath) ?? string.Empty);

// Получаем десериализованный storage объекта (контент, загруженный из внешних источников, будет находиться в нем), список файлов внешнего контента, результат валидации. (List<object> deserializedStorageObject, IList<string> externalFileNames, IValidationResultBuilder getContentFailedValidationResult) = await this.storageSerializer.DeserializeAsync(json, GetFileContentStream, contentDirectoryName);

// под индексом [0] deserializedStorageObject содержит storage объекта Card, под последующими индексами, содержится информация о прикрепленных файлах (если такие есть). // Например, дальнейшими действиями, можем создать запрос на сохранение карточки и т.д. var cardStoreRequest = null; if(deserializedStorageObject[0] is Dictionary<string, object> requestStorage) { cardStoreRequest = new CardStoreRequest(requestStorage); }

Back to top