我有一个只有几个多态类型成员的类。它不是像List这样的集合意义上的容器,只是一个类。
public class Stuff {
public BaseClassA MyA;
public BaseClassB MyB;
}
当然,BaseClassA和BaseClassB可以有各种子类。我需要能够将这些序列化和反序列化为JSON。我一直在使用Json.NET。
我想避免包含类型信息。对于简单的情况,让我们说每当我想要反序列化时,我就会知道MyA和MyB的具体类是什么。但是,如何告知Json.NET我的知识?我认为JsonConvert.DeserializeObject<Stuff>
将不起作用,因为它将尝试创建BaseClassA和BaseClassB的实例,而不是MyA和MyB最初的子类。
我能想到几个答案。我正在寻找更好的答案。为了清楚我要求的内容,我将举出一两个我能想到的例子。
我可以在Stuff
public static Stuff DeserializeMyStuff<TA, TB>(string json) where TA: BaseClassA where TB: BaseClassB
{
JsonSerializer serializer = new JsonSerializer();
JObject obj = JObject.Parse(json);
BaseClassA a = serializer.Deserialize<TA>(obj["MyA"].CreateReader());
BaseClassB b = serializer.Deserialize<TB>(obj["MyB"].CreateReader());
return new Stuff { MyA = a, MyB = b };
}
我可以使用未初始化的具体类型实例预填充Stuff,并使用已经存在的类型的自定义转换器。这样做的好处是Stuff对象可以是更大的东西的一部分,你可以序列化整个blob。
Stuff myStuff = new Stuff { MyA = new SpecificA(), MyB = new SpecificB() };
JsonConvert.PopulateObject(json, myStuff);
[JsonConverter(typeof(StuffConverter)]
public class Stuff {
...
public class StuffConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
BaseClassA a = serializer.Deserialize(obj["MyA"].CreateReader(), ((Stuff)existingValue).MyA.Type);
BaseClassB b = serializer.Deserialize(obj["MyB"].CreateReader(), ((Stuff)existingValue).MyB.Type);
return new Stuff { MyA = a, MyB = b };
}
}
我可以通过使用真实数据的访问器定义Stuff
来懒惰地反序列化
public class Stuff {
public JToken JsonA;
public JToken JsonB;
public BaseClassA GetMyA<T>() where T: BaseClassA { ... }
public BaseClassB GetMyB<T>() where T: BaseClassB { ... }
}
好的,现在对于更棘手的部分。有时当我反序列化时,我只会知道MyA的子类,而不是MyB。在这种情况下,我也不希望访问MyB,但如果我再次序列化,我确实希望保留它。第三种方法可以正常工作,第二种方法可能会被修改以处理它。
以前有人遇到过这个问题,并找到了一个很好的解决方案吗?