Есть задача, в которой нужно будет сериализовывать и десериализовывать 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;
Зверев Александр,
Благодарю! Такой способ оказался рабочим.