- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试编写一组类来表示一个特别复杂的对象,并且在其中一个类中,我有一个属性被设置为三个可能的派生类的基(抽象)类。我正在设置一个 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 { }
抽象类的派生类有3个:
[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 格式化程序无法填充派生类,留下属性 null
.
我可以混合 XmlSerializer
属性 DataContractSerializer
同一类的属性?我用的是XmlSerializer
因为我在我设计的 xml 中使用了 xml 属性,但是如果需要的话可以更改,因为我是自己开发 xml 模式。
在 Json.NET 中什么等同于 [KnownType()]
? Json.NET 似乎不尊重 DataContractSerializer
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)。
最佳答案
你可以像前面提到的那样混合,但我认为你不需要,我自己没有使用过 WEB api 但 WCF Rest 从 DataContracts 生成 xml 和 json(没有 Xml.. 标签),像这样标记你的类:
[DataContract]
public class FormulaStructure
{
[DataMember]
public AFormulaItemStructure FormulaItem;
}
[DataContract]
[KnownType(typeof(ColumnStructure))]
[KnownType(typeof(FunctionStructure))]
[KnownType(typeof(OperandStructure))]
public abstract class AFormulaItemStructure { }
[DataContract(Name="column")]
public class ColumnStructure : AFormulaItemStructure
{
[DataMember(Name="type")]
public string Type;
[DataMember(Name = "field")]
public string Field;
[DataMember(Name = "display")]
public string Display;
}
[DataContract(Name="function")]
public class FunctionStructure : AFormulaItemStructure
{
[DataMember(Name = "type")]
public string Type;
[DataMember(Name = "name")]
public string Name;
[DataMember(Name = "parameters")]
public string Parameters;
}
[DataContract(Name = "operand")]
public class OperandStructure : AFormulaItemStructure
{
[DataMember(Name = "type")]
public string Type;
[DataMember(Name = "left")]
public string Left;
[DataMember(Name = "right")]
public string Right;
}
如果您需要对生成的 XML/JSON 进行更多控制,则可能需要进一步调整。我用这段代码来测试:
public static string Serialize(FormulaStructure structure)
{
using (MemoryStream memoryStream = new MemoryStream())
using (StreamReader reader = new StreamReader(memoryStream))
{
var serializer = new DataContractSerializer(typeof(FormulaStructure));
serializer.WriteObject(memoryStream, structure);
memoryStream.Position = 0;
return reader.ReadToEnd();
}
}
public static FormulaStructure Deserialize(string xml)
{
using (Stream stream = new MemoryStream())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
stream.Write(data, 0, data.Length);
stream.Position = 0;
var deserializer = new DataContractSerializer(typeof(FormulaStructure));
return (FormulaStructure)deserializer.ReadObject(stream);
}
}
关于c# - 使用 Web API 反序列化为具有抽象属性的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12182164/
出于好奇,我尝试了一些原型(prototype)制作,但似乎只允许在第一个位置使用子例程的原型(prototype) &。 当我写作时 sub test (&$$) { do_somethin
我需要开发一个类似于 Android Play 商店应用程序或类似 this app 的应用程序.我阅读了很多教程,发现几乎每个教程都有与 this one 类似的例子。 . 我已经开始使用我的应用程
考虑一个表示“事件之间的时间”的列: (5, 40, 3, 6, 0, 9, 0, 4, 5, 18, 2, 4, 3, 2) 我想将这些分组到 30 个桶中,但桶会重置。期望的结果: (0, 1,
我是一名优秀的程序员,十分优秀!