Есть задача, в которой нужно будет сериализовывать и десериализовывать entity или коллекцию. Стандартное обращение к JsonConvert.SerializeObject не работает сходу, но можно настроить с помощью пользовательских объектов, чтобы отбрасывались лишние свойства. Но DeserializeObject сделать так и не получилось. В доках нашёл функционал в ядре системы, предназначенный для этой задачи. Получился примерно такой код:
public virtual string Serialize(Entity entity) { using (var textWriter = new StringWriter()) using (var writer = GetDataWriter(textWriter)) { entity.WriteData(writer); return textWriter.ToString(); } } public virtual Entity Deserialize(string schemaName, string stringValue) { var manager = UserConnection.EntitySchemaManager; var entitySchema = manager.GetInstanceByName(schemaName); var entity = entitySchema.CreateEntity(UserConnection); using (var textReader = new StringReader(stringValue)) using (var reader = GetReader(textReader)) { entity.ReadData(reader); return entity; } } protected override DataWriter GetDataWriter(TextWriter textWriter) { var settings = new JsonDataWriterSettings() { WriteDefValues = false, QuoteName = false }; var writer = new JsonDataWriter(settings, textWriter); return writer; } protected override DataReader GetReader(TextReader textReader) { var reader = new JsonDataReader(textReader); return reader; }
Аналогичный код для EntityCollection.
Сериализация в json таким образом работает. Но немного странно. В результирующей json-строке есть открывающая фигурная скобка, но нет закрывающей.
Десериализация в json не работает вообще. ReadData отрабатывает без исключений, но на выходе получается пустой экземпляр без заполненных колонок. Аналогичная проблема с EntityCollection. Только сама коллекция пустая.
Сериализация в xml оказалась вообще неработоспособной.
У кого-то получалось заставить этот функционал работать? Или может кто нашёл какой-то другой вариант решения задачи?
Нравится
Насколько понимаю, для Entity не используют DeserializeObject, в коде конфигурации его используют для фильтров и подобного. Например, для работы с данными в пакете есть свои функции в PackageSchemaDataUtilities: Deserialize и Serialize. Примеры из тестов, проверяющих работу с ними:
EntitySchema schema = CreateSchema("TestSchema", userConnection.EntitySchemaManager); AddIntegerColumn(schema, "ColumnInt"); AddTextColumn(schema, "ColumnText"); AddDateTimeColumn(schema, "ColumnDateTime"); PackageSchemaDataDescriptor dataDescriptor = CreateTestPackageSchemaData(schema.UId, schema.Name); foreach (var column in schema.Columns) { dataDescriptor.AddColumn(new PackageSchemaDataColumnDescriptor(column.UId, false)); } var testDateTime2012 = DateTime.Parse("2012-01-01 12:00"); TimeSpan testUtcOffset2012 = TimeZoneInfo.Local.GetUtcOffset(testDateTime2012); var testDateTime2013 = DateTime.Parse("2013-01-01 00:00"); TimeSpan testUtcOffset2013 = TimeZoneInfo.Local.GetUtcOffset(testDateTime2013); string columnIdUId = schema.Columns.GetByName("Id").UId.ToString(); string columnIntUId = schema.Columns.GetByName("ColumnInt").UId.ToString(); string columnTextUId = schema.Columns.GetByName("ColumnText").UId.ToString(); string columnDateTimeUId = schema.Columns.GetByName("ColumnDateTime").UId.ToString(); string data = @"{ ""PackageData"": [ { ""Row"": [ { ""SchemaColumnUId"": """ + columnIdUId + @""", ""Value"": ""f16d852d-d896-4792-99ff-f36fdd0ab2e4"" }, { ""SchemaColumnUId"": """ + columnIntUId + @""", ""Value"": 1 }, { ""SchemaColumnUId"": """ + columnTextUId + @""", ""Value"": ""test 1"" }, { ""SchemaColumnUId"": """ + columnDateTimeUId + @""", ""Value"": ""\/" + testDateTime2012.ToJsonFormat(testUtcOffset2012) + @"\/"" } ] }, { ""Row"": [ { ""SchemaColumnUId"": """ + columnIdUId + @""", ""Value"": ""8b022a83-796a-426c-8337-b6fd40525a49"" }, { ""SchemaColumnUId"": """ + columnIntUId + @""", ""Value"": 2 }, { ""SchemaColumnUId"": """ + columnTextUId + @""", ""Value"": ""test 2"" }, { ""SchemaColumnUId"": """ + columnDateTimeUId + @""", ""Value"": ""\/" + testDateTime2013.ToJsonFormat(testUtcOffset2013) + @"\/"" } ] } ] }"; var dataUtilities = new PackageSchemaDataUtilities(userConnection); ICollection<Entity> entities = dataUtilities.Deserialize(data.ToStream(), schema);
И обратное:
EntitySchema schema = CreateSchema("TestSchema", userConnection.EntitySchemaManager, false); EntitySchemaColumn columnText = AddTextColumn(schema, "ColumnText"); ICollection<Entity> entities = new Collection<Entity>(); var entity = schema.CreateEntity(userConnection); entity.SetColumnValue(columnText, "Column Text Value"); entities.Add(entity); string data; var dataUtilities = new PackageSchemaDataUtilities(userConnection); dataUtilities.SerializeColumnName = true; using (var dataStream = new MemoryStream()) { dataUtilities.Serialize(dataStream, entities, schema.Columns.Select(c => c.UId)); dataStream.Position = 0; data = StreamUtilities.GetStreamContent(dataStream); }
Чтобы работать с ними, используется:
using Terrasoft.Core.Packages;
Насколько понимаю, для Entity не используют DeserializeObject, в коде конфигурации его используют для фильтров и подобного. Например, для работы с данными в пакете есть свои функции в PackageSchemaDataUtilities: Deserialize и Serialize. Примеры из тестов, проверяющих работу с ними:
EntitySchema schema = CreateSchema("TestSchema", userConnection.EntitySchemaManager); AddIntegerColumn(schema, "ColumnInt"); AddTextColumn(schema, "ColumnText"); AddDateTimeColumn(schema, "ColumnDateTime"); PackageSchemaDataDescriptor dataDescriptor = CreateTestPackageSchemaData(schema.UId, schema.Name); foreach (var column in schema.Columns) { dataDescriptor.AddColumn(new PackageSchemaDataColumnDescriptor(column.UId, false)); } var testDateTime2012 = DateTime.Parse("2012-01-01 12:00"); TimeSpan testUtcOffset2012 = TimeZoneInfo.Local.GetUtcOffset(testDateTime2012); var testDateTime2013 = DateTime.Parse("2013-01-01 00:00"); TimeSpan testUtcOffset2013 = TimeZoneInfo.Local.GetUtcOffset(testDateTime2013); string columnIdUId = schema.Columns.GetByName("Id").UId.ToString(); string columnIntUId = schema.Columns.GetByName("ColumnInt").UId.ToString(); string columnTextUId = schema.Columns.GetByName("ColumnText").UId.ToString(); string columnDateTimeUId = schema.Columns.GetByName("ColumnDateTime").UId.ToString(); string data = @"{ ""PackageData"": [ { ""Row"": [ { ""SchemaColumnUId"": """ + columnIdUId + @""", ""Value"": ""f16d852d-d896-4792-99ff-f36fdd0ab2e4"" }, { ""SchemaColumnUId"": """ + columnIntUId + @""", ""Value"": 1 }, { ""SchemaColumnUId"": """ + columnTextUId + @""", ""Value"": ""test 1"" }, { ""SchemaColumnUId"": """ + columnDateTimeUId + @""", ""Value"": ""\/" + testDateTime2012.ToJsonFormat(testUtcOffset2012) + @"\/"" } ] }, { ""Row"": [ { ""SchemaColumnUId"": """ + columnIdUId + @""", ""Value"": ""8b022a83-796a-426c-8337-b6fd40525a49"" }, { ""SchemaColumnUId"": """ + columnIntUId + @""", ""Value"": 2 }, { ""SchemaColumnUId"": """ + columnTextUId + @""", ""Value"": ""test 2"" }, { ""SchemaColumnUId"": """ + columnDateTimeUId + @""", ""Value"": ""\/" + testDateTime2013.ToJsonFormat(testUtcOffset2013) + @"\/"" } ] } ] }"; var dataUtilities = new PackageSchemaDataUtilities(userConnection); ICollection<Entity> entities = dataUtilities.Deserialize(data.ToStream(), schema);
И обратное:
EntitySchema schema = CreateSchema("TestSchema", userConnection.EntitySchemaManager, false); EntitySchemaColumn columnText = AddTextColumn(schema, "ColumnText"); ICollection<Entity> entities = new Collection<Entity>(); var entity = schema.CreateEntity(userConnection); entity.SetColumnValue(columnText, "Column Text Value"); entities.Add(entity); string data; var dataUtilities = new PackageSchemaDataUtilities(userConnection); dataUtilities.SerializeColumnName = true; using (var dataStream = new MemoryStream()) { dataUtilities.Serialize(dataStream, entities, schema.Columns.Select(c => c.UId)); dataStream.Position = 0; data = StreamUtilities.GetStreamContent(dataStream); }
Чтобы работать с ними, используется:
using Terrasoft.Core.Packages;
Зверев Александр,
Благодарю! Такой способ оказался рабочим.