public abstract class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
[JsonProperty(Required = Required.Always)]
public string Type { 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; }
}
我已经有一个JSON转换器正在根据Type属性的值对这些对象进行反序列化。
public abstract class JsonCreationConverter<T> : JsonConverter
{
protected abstract T Create(Type objectType, JObject jObject);
public override bool CanConvert(Type objectType)
{
Type t = typeof(T);
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
T target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class PersonConverter : JsonCreationConverter<Person>
{
protected override Person Create(Type objectType, JObject jObject)
{
if(jObject["Type"] == null)
{
throw new ArgumentException();
}
string type = (string)jObject["Type"];
if(type == null)
{
throw new ArgumentException();
}
if(type.Equals("Employee", StringComparison.InvariantCultureIgnoreCase))
{
return new Employee();
}
else if (type.Equals("Artist", StringComparison.InvariantCultureIgnoreCase))
{
return new Artist();
}
return null;
}
}
string json = "[{\"Department\": \"Department1\",\"JobTitle\": \"JobTitle1\",\"FirstName\": \"FirstName1\",\"LastName\": \"LastName1\",\"Type\": \"Employee\"},{\"Skill\": \"Drawer\",\"FirstName\": \"FirstName1\",\"LastName\": \"LastName1\",\"Type\": \"Artist\"}]";
List<Person> person = JsonConvert.DeserializeObject<List<Person>>(json, new PersonConverter());
上述效果很好。
现在,我是以下课程:
public class City
{
public string Name { get; set; }
public int Population { get; set; }
public Person[] Persons { get; set; }
}
如何为这个可以使用Person类Converter初始化Persons属性的City类编写转换器?我最初的想法是将Persons部分提取为JObject,然后使用PersonConverter在其上调用Deserialize,类似于下面的ReadJson方法。
var p = jObject["Persons"].ToString();
List<Person> persons = JsonConvert.DeserializeObject<List<Person>>(p, new PersonConverter());
但是ReadJson在serializer.Populate方法中抛出异常,因为抽象类无法实例化。
有什么想法吗?以下是json字符串作为示例
string Cityjson = "{\"Name\": \"London\" , \"Population\": \"1000\" , \"Persons\": [{\"Department\": \"Department1\",\"JobTitle\": \"JobTitle1\",\"FirstName\": \"FirstName1\",\"LastName\": \"LastName1\",\"Type\": \"Employee\"},{\"Skill\": \"Drawer\",\"FirstName\": \"FirstName1\",\"LastName\": \"LastName1\",\"Type\": \"Artist\"}]}";
方法#1
我通过
解决了这个问题1)在反序列化中标记人员属性
[JsonIgnore]
public Person[] Persons { get; set; }
2)在Create方法中实例化City对象并使用Person转换器初始化Persons属性
protected override City Create(Type objectType, JObject jObject)
{
if (jObject["Persons"] == null)
{
throw new ArgumentException();
}
var p = jObject["Persons"].ToString();
List<Person> persons = JsonConvert.DeserializeObject<List<Person>>(p, new PersonConverter());
var city = new City();
city.Persons = persons.ToArray();
return city;
}
ReadJson方法会像往常一样填充剩余的城市房产
还有其他方法吗?
答案 0 :(得分:0)
我认为这是最合适的方式
在ReadJson中传递数组时它基本上崩溃了,因为Jarray不是jboject。所以,我更新了ReadJson,如下所示,它有效。
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
JArray jObject = JArray.Load(reader);
List<T> list = new List<T>();
for (int i = 0; i < jObject.Count(); i++)
{
var p = jObject[i];
JObject ob = p as JObject;
T value = Create(objectType, ob);
serializer.Populate(ob.CreateReader(), value);
list.Add(value);
}
return list.ToArray();
}
else
{
JObject jObject = JObject.Load(reader);
T target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
是的,我不需要CityConverter。添加PersonConverter就足够了。