gpt4 book ai didi

c# - 使用 Web API 反序列化为具有抽象属性的类

转载 作者:太空狗 更新时间:2023-10-30 01:07:30 27 4
gpt4 key购买 nike

我正在尝试编写一组类来表示一个特别复杂的对象,并且在其中一个类中,我有一个属性被设置为三个可能的派生类的基(抽象)类。我正在设置一个 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com