I'm calling a .NET Web Api from an Angular client and I use JSON to serialize / deserialize data.
I'm trying to deserialize a Model object which contains a list of Detector. Detector is an abstract class with two inherited childs: TextDetector and ColorDetector.
To be able to recognize which type of Detector need to be instanciated during deserialization, I've set TypeNameHandling.Auto to my JsonSerializerSettings (.NET side).
Typical get response for a Model containing a TextDetector
{
"Detectors": {
"$type": "System.Collections.Generic.HashSet`1[[I2D_Api.Models.Detector, I2D Api]], System.Core",
"$values": [
{
"$type": "I2D_Api.Models.TextDetector, I2D Api",
"Id": 1,
"Name": "Detector0",
"Bounds": "0, 0, 0, 0"
}
]
},
"Id": 1,
"Name": "Modèle 0",
"ImgModelLink": "https://gamewave.fr/static/images/medias/upload/Fortnite/canards/Fortnite_20180515121231.jpg"
}
But I don't like this solution (which I can't even make work) because this would suggest that I have to MANUALLY typed my data on each client side request (Post or Put) to be correctly deserialize .NET side... In addition to that, I have not succeed yet in deserialize this JSON into a Model object client side because of the $ prefixes (but this is faisible i guess)
I think i'm going the wrong way, I've search but can't find another way to pass this collection, and this seems to be way to dirty. Is there another way to do this ?
Note: i'm using EntityFramework, this is my get method
[ResponseType(typeof(Model))]
public IHttpActionResult GetModel(int id)
{
Model model = db.Models.Find(id);
if (model == null)
{
return NotFound();
}
return Ok(model);
}
EDIT: So I followed @dbc link : Deserializing polymorphic json classes without type information which is EXACTLY what I want. I implemented a Json converter, which know child class to instanciate based on missing property Color (no color property = TextDetector, color property = ColorDetector).
Also replaced my Bounds property (JsonProperty.ValueProvider was unable to extract value on struct) by X, Y, Width and Height properties in Detector class (not an issue). Finally changed TypeNameHandling to Object.
But now I got a stackoverflow exception which I don't understand. Notice that TextDetector has no more attributes / properties than Detector Errors comes from this line in my DetectorConverter
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader); // This throw stackoverflow exception
if (item["Color"] == null)
{
return item.ToObject<TextDetector>();
}
else
{
return item.ToObject<ColorDetector>();
}
}
On first ReadJson execution, no exception. But then, it look like JObject.load(reader) causing a loop internally which i can't see in the stack beaucause it's external code. Only thing I know is that item type after loading from reader is Detector at first execution and then TextDetector, looping forever..