使用WebAPI进行JSON.NET抽象/派生类反序列化2

时间:2013-12-05 19:24:14

标签: c# .net asp.net-web-api json.net

我正在实现一个使用JSON.NET进行序列化的Web API 2服务。

当我尝试PUT(deseralize)更新的json数据时,抽象类不存在意味着它不知道如何处理它所以它什么也没做。我也尝试使类不是抽象的,只是从它继承,然后每个PUT都被解除分类到基类而不是缺少类的缺少类的属性。

示例:

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;}
}

将我的web api配置为进行typename处理:

public static void Register(HttpConfiguration config)
{
     config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = 
            TypeNameHandling.Objects;
}

然后我把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" }] }

缺少继承的属性。任何人都遇到了这个问题,想出了什么?

5 个答案:

答案 0 :(得分:24)

$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"
   }]
 }

序列化程序能够将对象解除分离为正确的强制转换。一点都不喜欢!

答案 1 :(得分:1)

我现在已经尝试了你的方案,它运行正常。但我确实注意到你在json输入中的,属性之后缺少id(逗号)。

我通过在我的操作中使用以下ModelState有效性检查来解决这个问题,然后在我的请求有效负载中显示错误。这对你也很有用:

if (!ModelState.IsValid)
{
    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState);
}

答案 2 :(得分:1)

我知道这篇文章现在已经过时了,答案已经标记了,但我认为我的解决方案可能会有所帮助....

尝试将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;}
    }

答案 3 :(得分:1)

JsonSubTypes库允许指定给定类的哪个子类应该用于反序列化为via属性,就像Java中的Jackson库一样。更具体地说,您可以:

  • 选择一个字段并为每个子类指定其值,或
  • 指定仅存在于某个子类中的字段。

答案 4 :(得分:-1)

我有一个非常类似的问题。对我有用的是添加一个初始化类中对象的默认构造函数。确保初始化每个对象。 在您的情况下,您需要将构造函数添加到People类。

public class People
{
  public People()
  {
     People = new List<Person>();
  }
  public List<Person> People { get;set; }
}

此外,这似乎是一个全有或全无的镜头。如果不初始化任何包含的对象,则它们都不包含值。