我正在从一组搜索结果的服务接收JSON。"结果"数组中的每个对象都可以是两种类型的对象之一(猫/狗我的例子)。下面是一些示例 JSON:
{
"total": 2,
"results": [
{
"type": "cat",
"id": "1",
"name": "Kitty"
},
{
"type": "dog",
"id": "2",
"name": "Rover",
"cat": {
"id": "3",
"name": "Missy"
}
}
]
}
我正在将 JSON 根对象反序列化为"搜索结果"。"结果"中的每个项目都是一个"搜索结果项目"。
以下是我的模型喜欢这些物品的方式:
public class Cat : SearchResultItem
{
public string id {get; set;}
public string name {get; set;}
}
public class Dog : SearchResultItem
{
public string id {get; set;}
public string name {get; set;}
public Cat {get; set;}
}
我创建了一个自定义转换器,用于转换为每个对象的正确类型:
public class SearchResultConverter : Newtonsoft.Json.Converters.CustomCreationConverter<SearchResultItem>
{
public override SearchResultItem Create(Type objectType)
{
throw new NotImplementedException();
}
public SearchResultItem Create(Type objectType, JObject jObject)
{
var type = (string)jObject.Property("type");
switch (type)
{
case "cat":
return new Cat();
case "dog":
return new Dog();
}
return null;
//throw new ApplicationException(String.Format("The given vehicle type {0} is not supported!", type));
}
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
var target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
我遇到的问题是狗碰巧有一个子项目是一只猫。我的转换器正在捕获此 Cat 对象并尝试对其进行转换。只有结果对象具有"类型"属性,子 Cat 或 Dog 的任何实例都没有此"类型"属性。缺少此属性会导致空引用异常。
如何将转换器限制为仅"结果"数组中的顶级项目?
可能最简单的方法是覆盖JsonConverter.CanConvert
并在typeof(SearchResultItem) == objectType
时返回true,而不是当它可以从objectType
分配时:
public class SearchResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SearchResultItem);
}
public override bool CanWrite
{
get { return false; }
}
public SearchResultItem Create(Type objectType, JObject jObject)
{
// As before
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// As before
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException("SearchResultConverter should only be used while deserializing.");
}
}
现在,仅当尝试反序列化 SearchResultItem
的实例时,才会调用转换器。 对于已声明为 Dog
或 Cat
类型的成员,将不会调用其 ReadJson()
方法。