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);
}