考虑下一个代码段:
static void Main(string[] args)
{
var classes = new Classes()
{
Instances = new A[]{
new B
{
BirthDate = DateTime.Now,
Name = "B1",
SomethingElse = "Test"
},
new C
{
Name = "C1",
SomethingElse1 = "Test2",
SomethingElse2 = "Test3",
}
}
};
var serialized = JsonConvert.SerializeObject(classes);
var deserialized = JsonConvert.DeserializeObject<Classes>(serialized);
}
}
public class Classes
{
public A[] Instances { get; set; }
}
public enum ClassType
{
B = 1,
C = 2
}
public class A
{
public string Name { get; set; }
public virtual ClassType ClassType { get; }
}
public class B : A
{
public string SomethingElse { get; set; }
public DateTime BirthDate { get; set; }
public override ClassType ClassType => ClassType.B;
}
public class C : A
{
public string SomethingElse1 { get; set; }
public string SomethingElse2 { get; set; }
public override ClassType ClassType => ClassType.C;
}
我需要将自己的逻辑注入避难所如何用继承来处理类。在这种情况下,我想根据JSON中的ClasStype属性做出决定。有什么想法/提示如何做?
顺便说一句。我知道我可以使用newtonsoft.json TypeNameHandling = TypeNameHandling.All
的功能,但是由于数据是从第三方系统发送的,因此我无法控制序列化过程。我控制的唯一一件事是挑选部分。
由于您不能使用TypeNameHandling
,因此必须先解析它,找到类型,然后进行挑选。
喜欢:
var jObj = Newtonsoft.Json.Linq.JObject.Parse(serialized);
var instances = jObj["Instances"].AsJEnumerable();
var myCol = new List<A>();
myCol.AddRange(instances.Select(x => (x["ClassType"] as JToken)
.ToObject<ClassType>() == ClassType.B ?
(x as JObject).ToObject<B>() :
(x as JObject).ToObject<C>());
感谢@zaitsman和@davidg我提出了对我有用的解决方案。在这里是:
public class AClassConverter : JsonConverter
{
private readonly Type[] _types;
public AClassConverter(params Type[] types)
{
_types = types;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var jObj = JObject.Load(reader);
var classType = jObj["ClassType"].ToObject<ClassType>();
return classType == ClassType.B ?
(A)jObj.ToObject<B>() :
(A)jObj.ToObject<C>();
}
public override bool CanRead => true;
public override bool CanWrite => false;
public override bool CanConvert(Type objectType)
{
return _types.Any(t => t == objectType);
}
}
何时进行审理:
var deserialized = JsonConvert.DeserializeObject<Classes>(serialized, new AClassConverter(typeof(A)));