I’m receiving JSON from a service which is a set of search results. Each object in the “results” array could be one of two types of objects (cat/dog I my example). Here’s some example JSON:
{
"total": 2,
"results": [
{
"type": "cat",
"id": "1",
"name": "Kitty"
},
{
"type": "dog",
"id": "2",
"name": "Rover",
"cat": {
"id": "3",
"name": "Missy"
}
}
]
}
I’m deserializing the JSON root object to “SearchResult”. Each item in the "results" is a “SearchResultItem”.
Here’s what my models like for the items:
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;}
}
I’ve created a custom converter to convert to the correct type for each object:
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;
}
}
The issue I’m having is that Dog happens to have a child item which is a Cat. My converter is catching this Cat object and trying to convert it. Only the results object have a “type” property, any instance of a child Cat or Dog won’t have this “type” property. The absence of this property is causing an Null Reference exception.
How do I restrict the converter to only the top level items in the “results” array?
Probably the easiest way to do this is to override
JsonConverter.CanConvert
and have it return true whentypeof(SearchResultItem) == objectType
, rather than when it is assignable fromobjectType
:Now the converter will be called only when attempting to deserialize an instance of
SearchResultItem
. For members already declared to be of typeDog
orCat
itsReadJson()
method will not get called.