I have two 'data' classes:
public class BaseData
{
public string BaseDataStuff { get; set; }
}
public class ChildData : BaseData
{
public string ChildDataStuff { get; set; }
}
and a 'container' class:
public class Container
{
public BaseData Data { get; set; }
}
Then I have the following controller:
public class Controller : ControllerBase
{
private readonly ChildData Data;
private readonly Container Container;
public Controller()
{
Data = new ChildData()
{
BaseDataStuff = "base stuff",
ChildDataStuff = "child stuff"
};
Container = new Container()
{
Data = Data
};
}
[HttpGet("data")]
public ActionResult<BaseData> GetData() => Ok(Container.Data);
[HttpGet("container")]
public ActionResult<Container> GetContainer() => Ok(Container);
}
The first method just returns the ChildData
instance. When I run it in swagger, I get the JSON I expect:
{
"childDataStuff": "child stuff",
"baseDataStuff": "base stuff"
}
When I run the second method through swagger, it looks like it casts the ChildData
instance to BaseData
. I get the following JSON:
{
"data": {
"baseDataStuff": "base stuff"
}
}
Can someone explain what is happening here please?
CodePudding user response:
You could try serializing yourself like this
options = new JsonSerializerOptions
{
WriteIndented = true
};
jsonString = JsonSerializer.Serialize<object>(Container, options);
or another option, is to explicitly mark them as serializable for the serializer:
[DataContract]
public class BaseData
{
[DataMember]
public string BaseDataStuff { get; set; }
}
[DataContract]
public class ChildData : BaseData
{
[DataMember]
public string ChildDataStuff { get; set; }
}
CodePudding user response:
This question was interesting. See How to serialize properties of derived classes with System.Text.Json
There it explains that System.Text.Json does not handle serializing polymorphic objects the way you want prior to .NET 7. There are some work arounds but those allow you to serialize when the root object is polymorpic (Container in you case) but not members of the root (BaseData and ChildData).
In .NET 7 you can do this
using System.Text.Json.Serialization;
[JsonDerivedType(typeof(ChildData))]
public class BaseData
{
public string BaseDataStuff { get; set; } = string. Empty;
}
and
public class ChildData : BaseData
{
public string ChildDataStuff { get; set; } = string. Empty;
}
and
public class Container
{
public BaseData Data { get; set; } = new BaseData();
}
Then this
var data = new ChildData()
{
BaseDataStuff = "base stuff",
ChildDataStuff = "child stuff"
};
var container = new Container
{
Data = data
};
jsonString = JsonSerializer.Serialize(container);
Console.WriteLine(jsonString);
gives you
{"Data":{"ChildDataStuff":"child stuff","BaseDataStuff":"base stuff"}}
Which I think is what you want. Of course, going to .NET 7 may not be convenient.