c# .net asp.net-web-api json.net

c# - JSON.NET Deserialización de clase abstracta/derivada con WebAPI 2



asp.net-web-api (4)

Estoy implementando un servicio Web API 2 que usa JSON.NET para la serialización.

Cuando trato de PONER (deserealizar) los datos json actualizados, la clase abstracta no está presente, lo que significa que no sabía qué hacer con ella, por lo que no hizo nada. También intenté hacer que la clase NO fuera abstracta y simplemente heredara de ella y luego cada PUT deseralizó a la clase base en lugar de a la clase derivada que carecía de las propiedades de la clase derivada.

Ejemplo:

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

con mi API web configurada para hacer el manejo de nombres de tipos:

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

luego PUSE el JSON como:

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

al método de la API web:

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

pero el resultado al inspeccionar el value siempre es:

People == { People: [] }

o si no es abstracto

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

falta la propiedad heredada. ¿Alguien se encontró con este problema y se le ocurrió algo?


He intentado tu escenario ahora y funciona bien. Pero noté que te falta un , (coma) después de la propiedad de id en tu entrada json.

Lo descubrí usando la siguiente verificación de validez ModelState en mi acción, que luego mostró el error en la carga útil de mi solicitud. Esto podría serle útil a usted también:

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


La función $type tiene que ser el primer atributo en el objeto.

En el ejemplo anterior lo hice:

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

después de mover $type a la parte superior como:

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

el serializador fue capaz de desrealizar el objeto al molde correcto. Tengo que amar eso!


Sé que esta publicación ya es antigua y la respuesta ha sido marcada, pero pensé que mi solución podría ser útil ...

Intente agregar el atributo JsonProperty a las propiedades en su clase abstracta.

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


Tuve un problema muy similar. Lo que funcionó para mí fue agregar un constructor predeterminado que inicializa los objetos en su clase. Asegúrese de inicializar cada objeto. En su caso, debe agregar el constructor a la clase People.

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

Además, esto parece ser un tiro de todo o nada. Si no inicializa ningún objeto contenido, ninguno de ellos contendrá valores.