【问题标题】:How do Idesign a generic class to deserialize this XML?如何设计一个通用类来反序列化 XML?
【发布时间】:2019-09-07 10:10:30
【问题描述】:

我正在尝试编写用于反序列化来自某些 API 的 XML 响应的类。

这是一个示例响应。当我查询 ObjectA 时,

<Response>
    <Status>0</Status>
    <Message>Ok</Message>
    <Data>
        <ObjectAs>
            <Count>2</Count>
            <ObjectA>...</ObjectA>
            <ObjectA>...</ObjectA>
        </ObjectAs>
    </Data>
</Response>

当我查询 ObjectB 时,

<Response>
    <Status>0</Status>
    <Message>Ok</Message>
    <Data>
        <ObjectBs>
            <Count>1</Count>
            <ObjectB>...</ObjectB>
        </ObjectBs>
    </Data>
</Response>

我正在尝试创建一个通用的 Response 类,但我尝试的一切似乎都是徒劳的。

我无法更改响应结构。而且我试图避免为每种响应类型编写一个新的响应类。

请注意在数据下,每个 API 响应是不同的。对于 ObjectA,它是 &lt;ObjectAs&gt;,对于 ObjectB,它是 &lt;ObjectBs&gt;

这是我的 ApiResponse 类,

[XmlRoot(ElementName = "Response")]
    public class ApiResponse<T>
    {
        public int Code { get; set; }

        public string Message { get; set; }

        [XmlAnyElement("Data")]
        public XmlElement DataElement { get; set; }

        [XmlIgnore]
        public List<T> Data
        {
            get
            {
                {
                    return null; // How do I parse and return the list of Objects (A, B, C, whatever?)
                }
            }
        }
    }

这是我查询设备时的示例 API XML 响应。

<Response>
  <Code>0</Code>
  <Message>OK</Message>
  <Data>
    <Devices>
      <Count>2</Count>
      <Device>
        <Name>0001</Name>
        <Active>TRUE</Active>
        <DeviceType>1</DeviceType>
        <Address>192.168.0.75</Address>
        <Port>80</Port>
        <Memo/>
      </Device>
      <Device>
        <Name>0002</Name>
        <Active>TRUE</Active>
        <DeviceType>1</DeviceType>
        <Address>192.168.0.78</Address>
        <Port>80</Port>
      </Device>
    </Devices>
  </Data>
</Response>

当我查询用户时,

<Response>
  <Code>0</Code>
  <Message>OK</Message>
  <Data>
    <Users>
      <Count>1</Count>
      <User>
        <Name>Administrator</Name>
        <Group>Admins</Group>
      </User>
    </Users>
  </Data>
</Response>

【问题讨论】:

  • @Progman 这是一个不同的问题。注意在 Data 下,每个 api 响应是不同的。对于 ObjectA,它是 ObjectAs,对于 ObjectB,它是 ObjectBs。此外,还有一个 Count 元素,而不仅仅是一个 Objects 数组。
  • 您是否尝试过使用[XmlAnyElement] 属性?请edit 您的问题包括您尝试使用[XmlAnyElement] 属性以及它如何未能获得您想要的值/结果。
  • 创建一个对象 A 和 B 都继承的基本类型。您需要使用 XmlInclude 属性。此方法向 xml 添加一个额外的类型属性。请参阅:docs.microsoft.com/en-us/dotnet/api/…

标签: c# xml deserialization


【解决方案1】:

这是一个使用LINQ to XML 的通用解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            ApiResponse apiResponse = new ApiResponse(FILENAME);
        }
    }


    public class ApiResponse
    {
        public int code { get; set; }
        public string message { get; set; }
        public string _type { get; set; }
        public int count { get; set; }

        public Dictionary<string, Dictionary<string, string>> dict { get; set; }


        public ApiResponse(string filename)
        {
            XDocument doc = XDocument.Load(filename);
            XElement response = doc.Root;
            code = (int)response.Element("Code");
            message = (string)response.Element("Message");

            XElement types = (XElement)response.Element("Data").FirstNode;
            _type = types.Name.LocalName;
            count = (int)types.Element("Count");
            dict = types.Elements().Where(x => x.Name.LocalName != "Count")
                .GroupBy(x => (string)x.Element("Name"), y => y.Elements()
                    .GroupBy(a => a.Name.LocalName, b => (string)b)
                    .ToDictionary(a => a.Key, b => b.FirstOrDefault()))
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        }
    }
}

【讨论】:

  • 谢谢。但这不是我想要达到的目标。我想做的是反序列化问题中的 xml 的通用类。我什至不确定这是否可能。
  • 为什么需要上课?您可以随时获取字典中的字符串并让您上课。
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多