JSON.NET Аннотация/десериализация производного класса с помощью WebAPI 2
Я реализую службу веб-API 2, которая использует JSON.NET для сериализации.
Когда я пытаюсь обновить json-данные PUT (deseralize), абстрактный класс отсутствует, потому что он не знал, что с ним делать, поэтому ничего не делал. Я также попытался сделать класс NOT абстрактным и просто наследовать от него, а затем каждый PUT был обработан в базовом классе, а не в классе derrive, у которого отсутствуют свойства класса derrive.
Пример:
public class People
{
// other attributes removed for demonstration simplicity
public List<Person> People { get;set; }
}
public abstract class Person
{
public string Id {get;set;}
public string Name {get;set;}
}
public class Employee : Person
{
public string Badge {get;set;}
}
public class Customer : Person
{
public string VendorCategory {get;set;}
}
с моим веб-api, настроенным на обработку имен типов:
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
TypeNameHandling.Objects;
}
затем я PUT JSON, как:
{
people: [{
name: "Larry",
id: "123",
badge: "12345",
$type: "API.Models.Employee, API"
}]
}
для метода web api:
public HttpResponseMessage Put(string id, [FromBody]People value)
{
people.Update(value); // MongoDB Repository method ( not important here )
return Request.CreateResponse(HttpStatusCode.OK);
}
но вывод при проверке value
всегда:
People == { People: [] }
или если не абстрактный:
People == { People: [{ Name: "Larry", Id: "123" }] }
отсутствует свойство inheritited. Кто-нибудь столкнулся с этой проблемой и придумал что-нибудь?
Ответы
Ответ 1
Функция $type
должна быть первым атрибутом в объекте.
В приведенном выше примере я сделал:
{
people: [{
name: "Larry",
id: "123",
badge: "12345",
$type: "API.Models.Employee, API"
}]
}
после перемещения $type
вверху:
{
people: [{
$type: "API.Models.Employee, API",
name: "Larry",
id: "123",
badge: "12345"
}]
}
Сериализатор смог выполнить десарализацию объекта до правильного набора. Должен любить это!
Ответ 2
Я пробовал свой сценарий сейчас, и он отлично работает. Но я заметил, что вам не хватает ,
(запятая) после свойства id
в вашем json-входе.
Я понял это, используя следующую проверку работоспособности ModelState в моем действии, которая затем показала ошибку в моей полезной нагрузке запроса. Это может быть полезно и вам:
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState);
}
Ответ 3
Я знаю, что этот пост уже старый, и ответ был отмечен, но я думал, что мое решение может быть полезно....
Попробуйте добавить атрибут JsonProperty к свойствам вашего абстрактного класса.
using JTC.Framework.Json;
...
public class People
{
// other attributes removed for demonstration simplicity
public List<Person> People { get;set; }
}
public abstract class Person
{
[JsonProperty()]
public string Id {get;set;}
[JsonProperty()]
public string Name {get;set;}
}
public class Employee : Person
{
public string Badge {get;set;}
}
public class Customer : Person
{
public string VendorCategory {get;set;}
}
Ответ 4
У меня была очень похожая проблема. Что для меня работало, так это добавить конструктор по умолчанию, который инициализирует объекты в вашем классе. Убедитесь, что вы инициализируете каждый объект.
В вашем случае вам нужно добавить конструктор в класс People.
public class People
{
public People()
{
People = new List<Person>();
}
public List<Person> People { get;set; }
}
Кроме того, это, кажется, выстрел "все или ничего". Если вы не инициализируете какие-либо содержащиеся объекты, ни один из них не будет содержать значений.