JSON.NET:如何反序列化基础上的父(持有人)对象的值接口的财产? [英] JSON.NET: How to deserialize interface property based on parent (holder) object value?
问题描述
我有这样的类
class Holder {
public int ObjType { get; set; }
public List<Base> Objects { get; set; }
}
abstract class Base {
// ... doesn't matter
}
class DerivedType1 : Base {
// ... doesn't matter
}
class DerivedType2 : Base {
// ... doesn't matter
}
使用的WebAPI我想接收对象架
并正确反序列化。根据 OBJTYPE
价值,我需要对象
来进行反序列化财产无论是作为列表&LT; DerivedType1&GT;
( OBJTYPE == 1
)或列表&LT; DerivedType2&GT;
( OBJTYPE == 2
)。
Using WebAPI I want to receive the object Holder
and deserialize it correctly. Based on the ObjType
value I need Objects
property to be deserialized either as List<DerivedType1>
(ObjType == 1
) or List<DerivedType2>
(ObjType == 2
).
目前,我中搜寻和互联网的最好的方法,但我发现最好的是这个答案的http://计算器.COM / A /1038496分之8031283。这种解决方案的问题在于,它的父对象的宽松环境,所以我无法找到 OBJTYPE
的价值。 OK,我可以创建自定义的 JsonConverter
为架
和remebering的 OBJTYPE 解决code>价值,但我依然affraid这行
At the moment I searched SO and internet for best approach, but the best I've found is this answer http://stackoverflow.com/a/8031283/1038496. The problem of this solution is, that it loose context of parent object, so I cannot find out the value of ObjType
. OK, I could solve it by creating custom JsonConverter
for Holder
and remebering the ObjType
value, but still I'm affraid of this line
serializer.Populate(jObject.CreateReader(), target);
因为这个答案下面的评论说:
as the comment below this answer says
在ReadJson方法创建的新JsonReader不继承任何原始读者的配置值(文化,DateParseHandling,DateTimeZoneHandling,FloatParseHandling等)的。这些值应使用serializer.Populate()新JsonReader之前被复制。
The new JsonReader created in the ReadJson method does not inherit any of the original reader's configuration values (Culture, DateParseHandling, DateTimeZoneHandling, FloatParseHandling, etc...). These values should be copied over before using the new JsonReader in serializer.Populate().
这是我的问题,我自己复制这些值似乎并不干净,我(如果我错过了什么?)
which is problem for me and copying these values by myself doesn't seem clean to me (what if I miss something?)
所以,问题是:有没有更好的方法我已经错过了基于parent属性值进行反序列化抽象的对象属性
推荐答案
您是在正确的轨道上。你需要实现一个自定义的 JsonConverter
您架
类来处理这种情况下,如你所说。但是,不要担心,这是可以编写转换器以这样一种方式,你可以使用传递到转换器的原始阅读器和串行情况下,从来没有需要到设置在复制到新的实例。下面是我会怎么写:
You are on the right track. You do need to implement a custom JsonConverter
for your Holder
class to handle this situation, as you suggested. But, don't worry, it is possible to write the converter in such a way that you can use the original reader and serializer instances passed to the converter, without ever needing to copy the settings over to new instances. Here is how I would write it:
class HolderConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Holder));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Holder holder = new Holder();
holder.ObjType = (int)jo["ObjType"];
holder.Objects = new List<Base>();
foreach (JObject obj in jo["Objects"])
{
if (holder.ObjType == 1)
holder.Objects.Add(obj.ToObject<DerivedType1>(serializer));
else
holder.Objects.Add(obj.ToObject<DerivedType2>(serializer));
}
return holder;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
下面是一个快速演示:
class Program
{
static void Main(string[] args)
{
string json = @"
[
{
""ObjType"" : 1,
""Objects"" :
[
{ ""Id"" : 1, ""Foo"" : ""One"" },
{ ""Id"" : 2, ""Foo"" : ""Two"" },
]
},
{
""ObjType"" : 2,
""Objects"" :
[
{ ""Id"" : 3, ""Bar"" : ""Three"" },
{ ""Id"" : 4, ""Bar"" : ""Four"" },
]
},
]";
List<Holder> list = JsonConvert.DeserializeObject<List<Holder>>(json);
foreach (Holder holder in list)
{
if (holder.ObjType == 1)
{
foreach (DerivedType1 obj in holder.Objects)
{
Console.WriteLine("Id: " + obj.Id + " Foo: " + obj.Foo);
}
}
else
{
foreach (DerivedType2 obj in holder.Objects)
{
Console.WriteLine("Id: " + obj.Id + " Bar: " + obj.Bar);
}
}
}
}
}
[JsonConverter(typeof(HolderConverter))]
class Holder
{
public int ObjType { get; set; }
public List<Base> Objects { get; set; }
}
abstract class Base
{
public int Id { get; set; }
}
class DerivedType1 : Base
{
public string Foo { get; set; }
}
class DerivedType2 : Base
{
public string Bar { get; set; }
}
输出:
Id: 1 Foo: One
Id: 2 Foo: Two
Id: 3 Bar: Three
Id: 4 Bar: Four
这篇关于JSON.NET:如何反序列化基础上的父(持有人)对象的值接口的财产?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!