I'm trying to write a .NET Core API that returns a list of objects. The following class is being used for sending responses:
class AnimalResponse {
public IAnimal Animal { get; set; }
}
There is an empty interface:
interface IAnimal {
}
There are also 2 classes that implement this interface:
class Cat : IAnimal {
public string CatProperty { get; set; }
}
class Dog : IAnimal {
public string DogProperty { get; set; }
}
As you can see, the Animal
property of AnimalResponse
class can contain either a Cat
or a Dog
class object. This is how I send response:
var response = new AnimalResponse() {
Animal = new Cat() {
CatProperty = "Cat Property Value"
}
};
return JsonResult(response);
For some reason CatProperty
gets missing from an API response after serialization. API returns the following json: {Animal:{}}
.
So, how do I make it include all the class-specific properties?
Note: I'm using Microsoft.AspNetCore.Mvc.JsonResult
, not Newtonsoft.Json
.
1 install NewtonsoftJson
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
2 Configure Services
services.AddControllersWithViews().AddNewtonsoftJson();
Serialization of derived types works only if the variable type is object
.
In other words, everything will work if you redefine your AnimalResponse
:
class AnimalResponse {
public object Animal { get; set; }
}
You lose a bit of type safety, but you can get around that like so:
class AnimalResponse {
public AnimalResponse(IAnimal animal) { Animal = animal; }
public object Animal { get; }
}
This works because System.Text.Json
has a special case for object
.
(There are a few articles out there that explain why and how to work with this, but unfortunately, it was a while ago since I found the one that actually made it clear for me.)
If you read also here Why are interfaces not [Serializable]? interfaces are not serializable because they define a contract and not a data.
They are a way to define a behaviour for the class.
By the way you should be able to make it serializable by implementing the ISerializable interface.
EDIT: Consider using a base Class instead of an Interface if you only need to serialize data. If you need to have both maybe a better solution is to have a base Class and an Interface and implement both.
UPDATE: Base class must implement the ISerializable interface.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.