1

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.

Hirasawa Yui
  • 1,138
  • 11
  • 29

3 Answers3

2

1 install NewtonsoftJson

Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson

2 Configure Services

services.AddControllersWithViews().AddNewtonsoftJson();

1

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.)

João Mendes
  • 1,719
  • 15
  • 32
0

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.

Michaelsoft
  • 777
  • 5
  • 18
  • The issue is still there after changing an interface to a class. – Hirasawa Yui May 04 '20 at 14:36
  • Make the class implement the ISerializable interface too. Sorry for the misunderstanding, an object that should be serialized must implement ISerializable, then in my opinion it's better that it is a class to implement it and not an interface, it could work too but IMHO it's going against the objectives of interfaces. – Michaelsoft May 04 '20 at 14:42