我想基于" meta"中的字段将json文档中的嵌套对象序列化为POCO(普通的旧c#对象)。该对象的区域,但我不知道如何做到这一点。
例如说我有以下文档:
{
"id": 123,
"type": "beer",
"_source": {
"name": "myBeer",
"brewery": "myBrewery",
"address": "blah"
}
}
使用此格式,源字段将映射到具有字段名称,啤酒厂和地址的另一个POCO。
现在说我在同一个索引中有另一个doc,其中包含以下字段:
{
"id": 345,
"type": "brewery",
"_source": {
"name": "mybrewery",
"date": "somedate",
"city": "somecity"
}
}
所以根据文档的类型变量,_source信息应序列化为不同的POCO。
我知道ShouldSerialize
方法适用于类中的属性,那么是否有类似于类的方法?基本上会根据条件将json对象序列化为特定的POCO?
答案 0 :(得分:1)
您需要存储合同信息以从外部元信息中解析正确的类型。
编写一个转换器类,它将为您完成整个工作:
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 BeerSource
{
[Newtonsoft.Json.JsonProperty( "name" )]
public string Name { get; set; }
[Newtonsoft.Json.JsonProperty( "brewery" )]
public string Brewery { get; set; }
[Newtonsoft.Json.JsonProperty( "address" )]
public string Address { get; set; }
}
public class BrewerySource
{
[Newtonsoft.Json.JsonProperty( "name" )]
public string Name { get; set; }
[Newtonsoft.Json.JsonProperty( "date" )]
public string Date { get; set; }
[Newtonsoft.Json.JsonProperty( "city" )]
public string City { get; set; }
}
真正的课程
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, } );
现在我们使用它的占地面积很小
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() );
答案 1 :(得分:0)
您可以在序列化继承的类型时实现此目的。序列化程序将自动将元属性添加到JSON文档,这将有助于反序列化为正确的类型。但是,您可能必须调整一些设置才能实现此目的。告诉我们您使用的是什么序列化程序,以便有人可以帮助您了解那些细节。
然而,无论如何你不应该这样做。这些元属性特定于所使用的序列化器。例如。 Web API 2的默认JSON序列化程序添加了一个名为“$type
”的属性,而Data Contract JSON序列化程序添加了一个名为“__type
”的属性。这意味着您在JSON提供程序和JSON使用者之间引入了紧密耦合 - 两者都被迫使用相同的序列化程序。
为_source
创建两种不同的类型:一种用于啤酒厂,另一种用于啤酒。这将为您和每个利益相关者节省很多麻烦。