【问题标题】:Deserialize XML generated from .NET Core 3.1 Web API反序列化从 .NET Core 3.1 Web API 生成的 XML
【发布时间】:2020-06-30 14:08:43
【问题描述】:

.NET Core 2.x 用于生成“普通”XML 格式,可以使用标准方法轻松反序列化,但现在,至少在 v3.1.5 中,在启动配置中使用 AddXmlDataContractSerializerFormatters 来启用 API 返回 XML返回看起来像这样的响应...

<ArrayOfArrayOfKeyValueOfstringanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <ArrayOfKeyValueOfstringanyType>
        <KeyValueOfstringanyType>
            <Key>districtId</Key>
            <Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:decimal">122</Value>
        </KeyValueOfstringanyType>
        <KeyValueOfstringanyType>
            <Key>amount</Key>
            <Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:decimal">1888810.42</Value>
        </KeyValueOfstringanyType>
    </ArrayOfKeyValueOfstringanyType>
    <ArrayOfKeyValueOfstringanyType>
        <KeyValueOfstringanyType>
            <Key>districtId</Key>
            <Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:decimal">205</Value>
        </KeyValueOfstringanyType>
        <KeyValueOfstringanyType>
            <Key>amount</Key>
            <Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:decimal">1207736.00</Value>
        </KeyValueOfstringanyType>
    </ArrayOfKeyValueOfstringanyType>
</ArrayOfArrayOfKeyValueOfstringanyType>

当尝试在客户端代码中反序列化时使用

var serializer = new XmlSerializer(typeof(List<MyDto>));
var reader = new StringReader(content);
var list = (List<MyDto>)serializer.Deserialize(reader);

抛出异常是可以理解的

InvalidOperationException: <ArrayOfArrayOfKeyValueOfstringanyType xmlns='http://schemas.microsoft.com/2003/10/Serialization/Arrays'> was not expected.

本例中使用的 DTO 很简单

public class MyDto
{
    public decimal DistrictId { get; set; }
    public decimal Amount { get; set; }
}

所以它期待与此类似的 XML,它可以正常工作

<ArrayOfMyDto>
  <MyDto>
    <DistrictId>122</DistrictId>
    <Amount>1888810.42</Amount>
  </MyDto>
  ... more items in list here
</ArrayOfMyDto>

有人知道如何反序列化现在在 .NET Core 3.1.5 中返回的这种 XML 格式吗?

更新:

在我的情况下,真正的问题是我需要反序列化的 XML 看起来确实如此,因为它是 ExpandoObjects 的序列化列表,而不是常规 DTO 的列表,即使常规 DTO 是 expando 对象中的数据源.

对于常规 DTO 列表,我会使用 AddXmlSeralizerFormatters,它会反序列化包含在“ArrayOf”中的 DTO 列表。

我使用 AddXmlSerializerFormatters 和 AddXmlDataContractSerializerFormatters 以及常规 DTO 列表和 ExpandoObjects 列表执行了一系列测试,以确定行为以及在不编写自定义类来反序列化此 XML 响应的情况下可以做什么:

从客户的角度来看:

  1. AddXmlSerializerFormatters 可以处理常规对象 (DTO) 的常规列表以进行序列化或反序列化
  2. AddXmlSerializerFormatters 无法处理序列化或反序列化的动态对象 (ExpandoObject) 列表(406 不可接受)
  3. AddXmlDataContractSerializerFormatters 可以处理常规对象列表 (DTO) 的序列化,但不能处理反序列化 (InvalidOperationException)
  4. AddXmlDataContractSerializerFormatters 可以处理动态对象 (ExpandoObject) 列表的序列化但不能反序列化 (InvalidOperationException)
  5. 同时使用两个 Formatter,首先在管道中使用 AddXmlSerializerFormatters,是否允许将序列化和反序列化传递给 AddXmlDataContractSerializerFormatters,因为前者返回 406 Not Acceptable,并且观察到后者的行为
  6. 同时使用两个格式化程序,首先在管道中使用 AddXmlDataContractSerializerFormatters,不允许此通过,因为返回 InvalidOperationException 并停止处理

从服务器的角度来看:

  1. AddXmlSerializerFormatters 不能处理常规对象 (DTO) 的 POST(400 错误请求),并且不能传递给可以处理它的 AddXmlDataContractSerializerFormatters

因此,总而言之,无需为“ArrayOf”包装的 XML 编写自定义 DTO 即可预期的最佳行为是在客户端应用程序中使用 AddXmlSerializerFormatters,然后使用 AddXmlDataContractSerializerFormatters,并在服务器应用程序中仅使用 AddXmlDataContractSerializerFormatters

或者更好的是,在您的服务器上完全抛弃 XML 并使用 JSON:P

【问题讨论】:

  • xml 序列化程序不接受列表对象 (List),因此您应该使用 MyDto。所以你的联系人应该是 ArrayOfKeyValueOfstringanyType 然后你需要两个类 ArrayOfKeyValueOfstringanyType 和 KeyValueOfstringanyType
  • 我发现确实不能使用 AddXmlDataContractSerializerFormatters 反序列化 DTO 或 ExpandoObject 列表。但是,使用 AddXmlSerializerFormatter 可以处理 DTO 列表而不是 ExpandoObjects 列表,而不使用您建议的自定义类

标签: c# xml serialization .net-core


【解决方案1】:

 private void deserializxml()
        {
            string myxmlstr = @"<ArrayOfMyDto>
  <MyDto>
    <DistrictId>122</DistrictId>
    <Amount>1888810.42</Amount>
  </MyDto>
 
</ArrayOfMyDto>";
            XmlSerializer serializer = new XmlSerializer(typeof(List<MyDto>), new XmlRootAttribute("ArrayOfMyDto"));
            StringReader stringReader = new StringReader(myxmlstr);
            List<MyDto> addList = (List<MyDto>)serializer.Deserialize(stringReader);

        }

【讨论】:

  • 使用 System.Xml.Serialization;
猜你喜欢
  • 2023-03-24
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 2018-04-23
  • 2017-08-01
  • 2021-02-10
  • 1970-01-01
相关资源
最近更新 更多