我正在尝试编写一组类来表示一个特别复杂的对象,在其中一个类中,我有一个属性被设置为三个可能的派生类的基(抽象)类。我正在设置一个 ASP.NET Web API 来处理序列化和反序列化,这意味着默认情况下,它使用 Json.NET 处理 JSON。如何让 Web API 将通过 POST 或 PUT 发送的 JSON 正确反序列化到正确的派生类中?
具有抽象成员的类看起来像这样(为了清楚起见,我包括了 Xml 装饰器,因为它们非常适合使用 XmlSerializer 反序列化 xml)
[Serializable]
public class FormulaStructure {
[XmlElement("column", typeof(ColumnStructure))]
[XmlElement("function", typeof(FunctionStructure))]
[XmlElement("operand", typeof(OperandStructure))]
public AFormulaItemStructure FormulaItem;
}
抽象类非常基本:
[Serializable]
public abstract class AFormulaItemStructure { }
抽象类有三个派生类:
[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;
}
目前,使用[DataContract]
属性,Json.NET 格式化程序无法填充派生类,留下 property null
。
问题
我可以将 XmlSerializer
属性与 DataContractSerializer
同一类的属性混合吗? 我使用 xml 是XmlSerializer
因为我在设计的 xml 中使用了 xml 属性,但如果有必要,可以更改它,因为我自己正在开发 xml 模式。
Json.NET 中的等价物是什么 [KnownType()]
?DataContractSerializer
Json.NET似乎不尊重KnownType
. 我需要滚动自己的 JsonConverter 来确定正确的类型吗?
我将如何装饰类以便 DataContractSerializer
或 DataContractJsonSerializer
将正确反序列化 Xml 和 Json 中的对象? 我的目标是将其放入 ASP.NET Web API,因此我希望能够灵活地生成 Xml 或 Json,以适应所请求的类型。如果 Json.NET 不起作用,是否需要使用其他格式化程序来处理这个复杂的类?
我需要能够在客户端生成对象,而不必在对象中包含 .NET 类名。
测试和改进
在我对 Web API 的测试中,默认的序列化发送到客户端:
{"FormulaItem":{"type":"int","field":"my_field","display":"My Field"}}
这对我的目的来说是理想的。但是,让它返回 API 并反序列化为正确的派生类型是行不通的(它会为属性生成 null)。
测试Tommy Grovnes下面的答案,DataContractSerializer
他用于测试生成:
{"FormulaItem":{"__type":"column:#ExpressionStructureExperimentation.Models","display":"My Field","field":"my_field","type":"int"}}
这对我或代码可维护性不起作用(如果我将整个命名空间硬编码到 JavaScript 中以生成这些对象,那么重构就变成了 PITA)。