简体   繁体   中英

Serialize interface as JsonResult

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM