我正在尝试扩展此处给出的JSON.net示例 http://james.newtonking.com/projects/json/help/CustomCreationConverter.html
我有另一个派生自基类/接口的子类
public class Person { public string FirstName { get; set; } public string LastName { get; set; } } public class Employee : Person { public string Department { get; set; } public string JobTitle { get; set; } } public class Artist : Person { public string Skill { get; set; } } List<Person> people = new List<Person> { new Employee(), new Employee(), new Artist(), };
我如何反序列化跟随Json回到List
[ { "Department": "Department1", "JobTitle": "JobTitle1", "FirstName": "FirstName1", "LastName": "LastName1" }, { "Department": "Department2", "JobTitle": "JobTitle2", "FirstName": "FirstName2", "LastName": "LastName2" }, { "Skill": "Painter", "FirstName": "FirstName3", "LastName": "LastName3" } ]
我不想使用TypeNameHandling JsonSerializerSettings。我专门在寻找定制的JsonConverter实现来处理此问题。网上的相关文档和示例很少。我似乎无法正确获得JsonConverter中重写的ReadJson()方法的实现。
使用该标准CustomCreationConverter,我正在努力工作如何生成正确的类型(Person或Employee),因为要确定此类型,您需要分析JSON,并且没有使用该Create方法执行此操作的内置方法。
CustomCreationConverter
Person
Employee
Create
我找到了一个与类型转换有关的讨论线程,事实证明它提供了答案。这是一个链接:类型转换。
所需要的是子类化JsonConverter,重写ReadJson方法并创建一个Create接受的新抽象方法JObject。
JsonConverter
ReadJson
JObject
JObject类提供了一种加载JSON对象的方法,并提供了对该对象内数据的访问。
重写的ReadJson方法创建一个JObject并调用该Create方法(由我们的派生转换器类实现),并传入JObject实例。
JObject然后可以通过检查某些字段的存在来分析此实例以确定正确的类型。
例
string json = "[{ \"Department\": \"Department1\", \"JobTitle\": \"JobTitle1\", \"FirstName\": \"FirstName1\", \"LastName\": \"LastName1\" },{ \"Department\": \"Department2\", \"JobTitle\": \"JobTitle2\", \"FirstName\": \"FirstName2\", \"LastName\": \"LastName2\" }, {\"Skill\": \"Painter\", \"FirstName\": \"FirstName3\", \"LastName\": \"LastName3\" }]"; List<Person> persons = JsonConvert.DeserializeObject<List<Person>>(json, new PersonConverter()); ... public class PersonConverter : JsonCreationConverter<Person> { protected override Person Create(Type objectType, JObject jObject) { if (FieldExists("Skill", jObject)) { return new Artist(); } else if (FieldExists("Department", jObject)) { return new Employee(); } else { return new Person(); } } private bool FieldExists(string fieldName, JObject jObject) { return jObject[fieldName] != null; } } public abstract class JsonCreationConverter<T> : JsonConverter { /// <summary> /// Create an instance of objectType, based properties in the JSON object /// </summary> /// <param name="objectType">type of object expected</param> /// <param name="jObject"> /// contents of JSON object that will be deserialized /// </param> /// <returns></returns> protected abstract T Create(Type objectType, JObject jObject); public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } public override bool CanWrite { get { return false; } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Load JObject from stream JObject jObject = JObject.Load(reader); // Create target object based on JObject T target = Create(objectType, jObject); // Populate the object properties serializer.Populate(jObject.CreateReader(), target); return target; } }