我在C#端上有一个类看起来像这样的课程:
[DataContract]
public class MyObject
{
[DataMember]
public SomeEnum FooType { get; set; }
[DataMember]
public FooBase MyFoo { get; set; }
}
基本上,属性FooType
中的值应该告诉您属性FooBase
中存在的MyFoo
派生的特定类型。
现在,如果我只想反序列化从FooBase
派生的对象,我可以执行以下操作:
var myFoo = JsonConvert.DeserializeObject(myJsonString, typeof(FooDerived)) as FooDerived;
但是如何反序列化嵌套MyObject
对象的FooBase
以及它的类型信息只能通过首先对对象进行部分反序列化来确定?
我认为这需要一个从JsonConverter派生的自定义转换器,但我不完全确定如何让ReadJson
在这里工作。
这样的东西?
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var result = new MyObject();
while(reader.Read())
{
if(reader.TokenType == JsonToken.PropertyName)
{
var prop = reader.Value as string;
if (prop == "FooType")
{
reader.Read();
result.FooType = (SomeEnum)reader.ReadAsInt32(); // or something like that
}
if (prop == "MyFoo")
{
reader.Read();
// now the reader.TokenType should be StartObject, but I can't
// deserialize the object because I don't know what type it is
// I might not have read "FooType" yet
// So I really need to pull this whole sub object out as a string
// and deserialize it later???
}
}
}
return result;
}
答案 0 :(得分:2)
将此答案用作灵感:https://stackoverflow.com/a/19308474/1250301
我想出了类似的东西:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObj = JObject.Load(reader);
var foo = jObj["MyFoo"];
var result = new MyObject();
result.FooType = jObj["FooType"].ToObject<SomeEnum>();
switch (result.FooType)
{
case SomeEnum.Value1:
result.MyFoo = foo.ToObject<FooType1>();
break;
case SomeEnum.Value2:
result.MyFoo = foo.ToObject<FooType2>();
break;
case SomeEnum.Value3:
result.MyFoo = foo.ToObject<FooType3>();
break;
default:
throw new Exception("Unknown FooType");
}
return result;
}
这里唯一的问题是,如果我向父对象添加新属性,我将需要手动映射它们。我想我可以做一些像:
var parent = jObj.ToObject<MyObject>();
然后填写MyFoo
对象,但这最终会再次调用ReadJson
。
答案 1 :(得分:1)
我相信您可以使用Json.Linq
来完成此任务。我不是在电脑前测试这个,但我相信它是这样的:
string fooTypeJson = JObject.Parse(myJsonString).SelectToken("FooType").ToString();
FooType fooType = reader.DeserializeObject<FooType>(fooTypeJson);