Подтвердить что ты не робот

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. Кто-нибудь столкнулся с этой проблемой и придумал что-нибудь?

4b9b3361

Ответ 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; }
}

Кроме того, это, кажется, выстрел "все или ничего". Если вы не инициализируете какие-либо содержащиеся объекты, ни один из них не будет содержать значений.