C# 根据条件选择要序列化到的POCO
我想根据对象“meta”区域中的字段将json文档中的嵌套对象序列化为POCO(纯旧c#object),但我不知道如何实现 例如,假设我有以下文档:C# 根据条件选择要序列化到的POCO,c#,json,inheritance,serialization,C#,Json,Inheritance,Serialization,我想根据对象“meta”区域中的字段将json文档中的嵌套对象序列化为POCO(纯旧c#object),但我不知道如何实现 例如,假设我有以下文档: { "id": 123, "type": "beer", "_source": { "name": "myBeer", "brewery": "myBrewery", "address": "blah" } } 使用这种格式,源字段将映射到另一个POCO,其中包含字段名称、酿酒厂和地址 现在,假设我
{
"id": 123,
"type": "beer",
"_source": {
"name": "myBeer",
"brewery": "myBrewery",
"address": "blah"
}
}
使用这种格式,源字段将映射到另一个POCO,其中包含字段名称、酿酒厂和地址
现在,假设我在同一索引中有另一个具有以下字段的文档:
{
"id": 345,
"type": "brewery",
"_source": {
"name": "mybrewery",
"date": "somedate",
"city": "somecity"
}
}
因此,基于文档的类型变量,\ u源信息应序列化为不同的POCO
我知道,
ShouldSerialize
方法适用于类中的属性,那么有类似的方法适用于类吗?基本上,这将根据条件将json对象序列化到特定的POCO?在序列化继承的类型时可以实现这一点。序列化程序将自动向JSON文档添加元属性,这将有助于反序列化为正确的类型。不过,您可能需要调整一些设置才能实现这一点。告诉我们您正在使用的序列化程序,以便有人可以帮助您了解具体情况
但是,无论如何,您不应该这样做。这些元属性特定于所使用的序列化程序。例如,Web API 2的默认JSON序列化程序添加了一个名为“$type
”的属性,而数据契约JSON序列化程序添加了一个名为“\uu type
”的属性。这意味着您在JSON提供者和JSON使用者之间引入了紧密耦合——两者都必须使用相同的序列化程序
为
\u source
创建两种不同的类型:一种用于酿酒厂,另一种用于啤酒。这将为您和每个利益相关者节省大量的麻烦。您需要存储合同信息,以便从外部元信息中解析正确的类型
编写一个将为您完成全部工作的转换器类:
public class DocConverter
{
private readonly Dictionary<string, Func<MetaInformation, object>> deserializers = new Dictionary<string, Func<MetaInformation, object>>();
private readonly Dictionary<Type, Func<object, string>> serializers = new Dictionary<Type, Func<object, string>>();
private class MetaInformation
{
[Newtonsoft.Json.JsonProperty( "id" )]
public int Id { get; set; }
[Newtonsoft.Json.JsonProperty( "type" )]
public string Type { get; set; }
[Newtonsoft.Json.JsonProperty( "_source" )]
public object Source { get; set; }
}
public void Register<Source, SourceData>( string contractName, Func<Source, Tuple<int,SourceData>> converter, Func<<Tuple<int, SourceData>, Source> reverter )
where Source : class
where SourceData : class
{
deserializers.Add( contractName,
( m ) =>
{
SourceData data = Newtonsoft.Json.JsonConvert.DeserializeObject<SourceData>( m.Source.ToString() );
return reverter( Tuple.Create( m.Id, data ) );
} );
serializers.Add( typeof( Source ),
( o ) =>
{
var data = converter( (Source) o );
var meta = new MetaInformation { Id = data.Item1, Type = contractName, Source = data.Item2, };
return Newtonsoft.Json.JsonConvert.SerializeObject( meta );
} );
}
public string Serialize( object source )
{
return serializers[ source.GetType() ]( source );
}
public object Deserialize( string jsonData )
{
var meta = Newtonsoft.Json.JsonConvert.DeserializeObject<MetaInformation>( jsonData );
return deserializers[ meta.Type ]( meta );
}
}
真正的阶级
public class Beer
{
public int Id { get; set; }
public string Name { get; set; }
public string Brewery { get; set; }
public string Address { get; set; }
}
public class Brewery
{
public int Id { get; set; }
public string Name { get; set; }
public string Date { get; set; }
public string City { get; set; }
}
毕竟,我们只注册合同名称、转换器和还原器
var conv = new DocConverter();
conv.Register<Beer, BeerSource>(
"beer",
( o ) => Tuple.Create( o.Id, new BeerSource { Name = o.Name, Brewery = o.Brewery, Address = o.Address, } ),
( t ) => new Beer { Id = t.Item1, Name = t.Item2.Name, Brewery = t.Item2.Brewery, Address = t.Item2.Address, } );
conv.Register<Brewery, BrewerySource>(
"brewery",
( o ) => Tuple.Create( o.Id, new BrewerySource { Name = o.Name, Date = o.Date, City = o.City, } ),
( t ) => new Brewery { Id = t.Item1, Name = t.Item2.Name, Date = t.Item2.Date, City = t.Item2.City, } );
var conv = new DocConverter();
conv.Register<Beer, BeerSource>(
"beer",
( o ) => Tuple.Create( o.Id, new BeerSource { Name = o.Name, Brewery = o.Brewery, Address = o.Address, } ),
( t ) => new Beer { Id = t.Item1, Name = t.Item2.Name, Brewery = t.Item2.Brewery, Address = t.Item2.Address, } );
conv.Register<Brewery, BrewerySource>(
"brewery",
( o ) => Tuple.Create( o.Id, new BrewerySource { Name = o.Name, Date = o.Date, City = o.City, } ),
( t ) => new Brewery { Id = t.Item1, Name = t.Item2.Name, Date = t.Item2.Date, City = t.Item2.City, } );
object source;
object result;
string jsonData;
source = new Beer { Id = 123, Name = "myBeer", Brewery = "myBrewery", Address = "blah", };
jsonData = conv.Serialize( source );
// check the JSON result
Console.WriteLine( jsonData );
result = conv.Deserialize( jsonData );
// check the result type
Console.WriteLine( result.GetType().ToString() );
source = new Brewery { Id = 456, Name = "myBrewery", Date = "somedate", City = "somecity", };
jsonData = conv.Serialize( source );
// check the JSON result
Console.WriteLine( jsonData );
result = conv.Deserialize( jsonData );
// check the result type
Console.WriteLine( result.GetType().ToString() );