Я звоню .NET Web Api с Angular клиента , и я использую JSON для сериализации / десериализации данных.
Я пытаюсь десериализовать объект Model , который содержит список Detector . Детектор - это абстрактный класс с двумя унаследованными потомками: TextDetector и ColorDetector .
Чтобы иметь возможность распознать, какой тип детектора должен быть создан во время десериализации, я установил TypeNameHandling.Auto для моего JsonSerializerSettings (сторона .NET).
Типичный ответ get для Модели, содержащей 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"
}
Но мне не нравится это решение (которое я даже не могу заставить работать), потому что оно предполагает, что я должен вручную вводить свои данные при каждом запросе на стороне клиента (Post или Put), чтобы правильно десериализовать сторону .NET. ... В дополнение к этому, мне еще не удалось десериализовать этот JSON в сторону объекта Model из-за префиксов $ (но это возможно, я думаю)
Я думаю, что я иду по неправильному пути, я ищу, но не могу найти другой способ передать эту коллекцию, и это кажется грязным. Есть ли другой способ сделать это?
Примечание : я использую EntityFramework, это мой метод get
[ResponseType(typeof(Model))]
public IHttpActionResult GetModel(int id)
{
Model model = db.Models.Find(id);
if (model == null)
{
return NotFound();
}
return Ok(model);
}
EDIT : Итак, я перешел по ссылке @dbc: Десериализация полиморфных классов json без информации о типе , что именно то, что я хочу. Я реализовал преобразователь Json, который знает, как создать дочерний класс на основе отсутствующего свойства Color (без свойства color = TextDetector, свойство color = ColorDetector).
Также заменил мое свойство Bounds ( JsonProperty.ValueProvider не удалось извлечь значение в структуре) на свойства X, Y, Width и Height в классе Detector (не проблема). Наконец изменилось TypeNameHandling на Объект .
Но теперь я получил исключение stackoverflow, которое я не понимаю. Обратите внимание, что TextDetector не имеет больше атрибутов / свойств , чем Detector
Ошибки появляются из этой строки в моем 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>();
}
}
При первом ReadJson выполнении, без исключения. Но тогда это выглядит как JObject.load (reader) , вызывая внутренний цикл, который я не вижу в стеке, потому что это внешний код. Единственное, что я знаю, это то, что тип элемента после загрузки из считывателя - Детектор при первом выполнении, а затем TextDetector , зацикливание навсегда ..