JSON.NET Abstract / Deserialize a derived class using WebAPI 2

I am implementing a web API 2 service that uses JSON.NET for serialization.

When I try to update the json data of PUT (deseralize), the abstract class is missing because it did not know what to do with it, therefore it did nothing. I also tried to make the NOT class abstract and simply inherit from it, and then each PUT was processed in the base class, and not in the derrive class, which does not have the properties of the derrive class.

Example:

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

with my web api configured to handle type names:

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

then i put json like:

 { people: [{ name: "Larry", id: "123", badge: "12345", $type: "API.Models.Employee, API" }] } 

for the web api method:

 public HttpResponseMessage Put(string id, [FromBody]People value) { people.Update(value); // MongoDB Repository method ( not important here ) return Request.CreateResponse(HttpStatusCode.OK); } 

but the output when checking value always:

 People == { People: [] } 

or if not abstract:

 People == { People: [{ Name: "Larry", Id: "123" }] } 

missing inheritited property. Has anyone encountered this problem and came up with something?

+18
c # asp.net-web-api
Dec 05 '13 at 19:24
source share
4 answers

The $type function must be the first attribute in the object.

In the above example, I did:

  { people: [{ name: "Larry", id: "123", badge: "12345", $type: "API.Models.Employee, API" }] } 

after moving $type at the top:

  { people: [{ $type: "API.Models.Employee, API", name: "Larry", id: "123", badge: "12345" }] } 

The serializer was able to desalaralize the object to the correct set. Gotta love it!

+22
Dec 09 '13 at 19:04 on
source share

I tried my script now and it works great. But I noticed that you are missing (a comma) after the id property in your json input.

I figured this out using the following ModelState health check in my action, which then showed an error in my request payload. It may be useful for you too:

 if (!ModelState.IsValid) { return Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState); } 
+1
Dec 05 '13 at 19:48
source share

I know this post is already old and the answer was noted, but I thought my solution might be useful ....

Try adding the JsonProperty attribute to the properties of your abstract class.

  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;} } 
+1
Feb 24 '15 at 7:28
source share

I had a very similar problem. What worked for me was to add a default constructor that initializes the objects in your class. Make sure you initialize each object. In your case, you need to add a constructor to the People class.

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

In addition, it seems to be an all-or-nothing shot. If you do not initialize any contained objects, none of them will contain values.

0
Oct 23 '15 at 2:51
source share



All Articles