У меня недавно была похожая проблема, но моя была, когда я принимал сообщения из очереди.Я решил это, сказав Newtonsoft добавить тип при сериализации моего объекта.Вы можете сделать это следующим образом:
JsonConvert.SerializeObject(response, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
С помощью SerializeObject
и DeserializeObject
вы можете передать некоторые дополнительные параметры сериализации.Здесь мы передаем новый экземпляр JsonSerializerSettings
этому параметру и устанавливаем для него TypeNameHandling
значение enum TypeNameHandling.All
.Это говорит Newtonsoft о включении типов всех сериализаций в сам JSON.Например, если у вас был класс, который выглядел так (на основе вашего примера JSON):
public class SuccessOne
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public SuccessOneChild Object { get; set; }
}
public class SuccessOneChild
{
public int Property1 { get; set; }
public string Property2 { get; set; }
}
Тогда полученный вами JSON будет выглядеть так:
{
"$type":"Functions.Tests.SuccessOne, Functions.Tests",
"StartDate":"2019-07-09T09:32:11.0090507+01:00",
"EndDate":"2019-07-16T09:32:11.0091048+01:00",
"Object":{
"$type":"Functions.Tests.SuccessOneChild, Functions.Tests",
"Property1":1,
"Property2":"someStr"
}
}
Обратите внимание надополнительные $type
свойства, которые были добавлены?Они были автоматически добавлены Newtonsoft, потому что вы указали это в настройках сериализации.
Затем, когда вы приступите к десериализации, вы также можете указать ему использовать обработку типов.Он будет смотреть на дополнительное свойство типа в вашем JSON и десериализовать в любой тип.При этом вам не нужно указывать DeserializeObject
аргумент типа:
var response = JsonConvert.DeserializeObject(response, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
Обратите внимание, что везде, где вы десериализуете, нужно знать о классах.Поэтому может быть полезно иметь эти классы в общей библиотеке, на которую могут ссылаться как ваш API, так и потребитель, чтобы избежать дублирования вашего кода.
Затем вы можете обрабатывать ответ в зависимости от его типа.Я сделал это с помощью оператора switch
:
switch (response.GetType().Name)
{
case nameof(SuccessOne):
var successOneResponse = (SuccessOne)response;
handleSuccessOne(successOneResponse);
break;
case nameof(SuccessTwo):
var successTwoResponse = (SuccessTwo)response;
handleSuccessTwo(successTwoResponse);
break;
default:
// Throw exception or whatever you want to do
break;
}
Я также создал скрипку, показывающую сериализацию и десериализацию здесь: https://dotnetfiddle.net/UcugGg