I am trying to write a set of classes to represent a particularly complex object, and in one of these classes I have a property that is set as a base (abstract) class of three possible derived classes. I am setting up the ASP.NET Web API to handle serialization and deserialization, which means that by default Json.NET uses JSON. How can I get the Web API to properly deserialize JSON sent via POST or PUT to the corresponding derived class?
A class with an abstract element looks like this (I want the clarity of Xml decorators to be clear, because they work just fine for deserializing xml with XmlSerializer)
[Serializable] public class FormulaStructure { [XmlElement("column", typeof(ColumnStructure))] [XmlElement("function", typeof(FunctionStructure))] [XmlElement("operand", typeof(OperandStructure))] public AFormulaItemStructure FormulaItem; }
The abstract class is pretty simple:
[Serializable] public abstract class AFormulaItemStructure { }
And there are three derivatives of the abstract class:
[Serializable] public class ColumnStructure: AFormulaItemStructure { [XmlAttribute("type")] public string Type; [XmlAttribute("field")] public string Field; [XmlAttribute("display")] public string Display; } [Serializable] public class FunctionStructure: AFormulaItemStructure { [XmlAttribute("type")] public string Type; [XmlAttribute("name")] public string Name; [XmlElement("parameters")] public string Parameters; } [Serializable] public class OperandStructure: AFormulaItemStructure { [XmlAttribute("type")] public string Type; [XmlElement("left")] public string Left; [XmlElement("right")] public string Right; }
Currently, using the [DataContract] attributes, Json.NET formatting does not populate the derived class, leaving the null property.
Questions
Is it possible to mix XmlSerializer attributes with DataContractSerializer attributes in one class? I use XmlSerializer because I use xml in the xml that I created, but this can be changed if necessary, since I am developing the xml schema myself.
What is equivalent in Json.NET for [KnownType()] ? Json.NET does not seem to support the version of DataContractSerializer KnownType . Do I need a roll of my JsonConverter to determine the correct type?
How to decorate classes so that DataContractSerializer or DataContractJsonSerializer properly deserialize objects in both Xml and Json? My goal is to put this in an ASP.NET web API, so I want to flexibly generate Xml or Json, depending on the type requested. Is there an alternative formatter that I need to use to work with this complex class if Json.NET does not work?
I need the ability to generate an object on the client side, not necessarily including .NET class names in it.
Testing and refinement
In my testing of the web API, serialization is sent to the client by default:
{"FormulaItem":{"type":"int","field":"my_field","display":"My Field"}}
which is perfect for my purposes. Returning to the API and deserializing to the corresponding derived types, however, does not work (it generates null for the property).
Testing Tommy Grovnes below, the DataContractSerializer that he used for testing generates:
{"FormulaItem":{"__type":"column:#ExpressionStructureExperimentation.Models","display":"My Field","field":"my_field","type":"int"}}
which doesnโt work for me or for the convenience of maintaining the code (refactoring becomes PITA if I hard-code the entire namespace in JavaScript to create these objects).