gpt4 book ai didi

xml - 反序列化对象列表产生空列表

转载 作者:行者123 更新时间:2023-12-04 04:44:46 24 4
gpt4 key购买 nike

我有一个 RESTful WCF 服务,我试图将任务列表发送到该服务。我在其他问题上发现你必须封装列表,我已经做到了,序列化看起来很顺利。

来自序列化列表的 XML 如下所示:

<?xml version="1.0" encoding="utf-8"?>
<MobileRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TaskRequests xmlns="MyNameSpace">
<MobileTask>
<TaskArgs xsi:type="GetUser">
<Password>test</Password>
<UserName>t</UserName>
</TaskArgs>
<TaskID>1</TaskID>
<TaskType>GetUser</TaskType>
</MobileTask>
<MobileTask>
<TaskArgs xsi:type="GetUser">
<Password>test</Password>
<UserName>t2</UserName>
</TaskArgs>
<TaskID>2</TaskID>
<TaskType>GetUser</TaskType>
</MobileTask>
</TaskRequests>
</MobileRequest>

所以 MobileRequest类有一个属性,它是 MobileTask 的列表对象。 MobileRequest 的代码类(class)非常简单,看起来像:

<Serializable(), DataContract(Name:="MobileRequest", [Namespace]:="MyNameSpace")> _
Public Class MobileRequest
<XmlArray()> <DataMember(Name:="TaskRequests")> _
Public TaskRequests As List(Of MobileTask) = New List(Of MobileTask)

Public Sub New()
Me.TaskRequests = New List(Of MobileTask)
End Sub
End Class

MobileTask 类如下所示:

<Serializable(), DataContract(Name:="MobileTask", [Namespace]:="MyNamespace"), _
KnownType(GetType(Obj.GetUser)), XmlInclude(GetType(Obj.GetUser))> _
Public Class MobileTask
Public Enum TypesOfTasks As Integer
Unknown = 0
GetUser = 1
End Enum

<DataMember(Name:="TaskID")> _
Public TaskID As Integer
<DataMember(Name:="TaskType")> _
Public TaskType As TypesOfTasks
<DataMember(Name:="TaskArgs")> _
Public TaskArgs As Object
End Class

TaskArgs 的类型取决于 TaskType。我已经为 TaskArgs 可能是的每种可能类型包含了一个 XMLInclude 和 KnownType 标记。 (这可能有点矫枉过正,但是当序列化的某些内容不起作用并且还没有尝试清理它时,我就这样做了)

我在测试应用程序中尝试反序列化 XML 的代码是:

Using logg As New System.IO.MemoryStream()
Using sw As New System.IO.StreamWriter(logg)
sw.Write(txtSource.Text)
sw.Flush()
If logg.Length > 0 Then
Using reader As New System.IO.StreamReader(logg)
logg.Position = 0
Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(SMS_VendorObj.MobileRequest))
Dim results = ser.Deserialize(logg)
End Using
End If
End Using
End Using

这是来自一个简单的 winform 设置,它允许我粘贴 XML 所以 txtSource只是一个文本框,我将从序列化中获得的 XML 放入其中。

在运行测试应用程序时,我可以单步执行上述反序列化代码并在 Dim results = ser.Deserialize(logg) 之后线路 results是正确的类型,但 MobileTask列表不包含任何项目。

我是否在类文件中遗漏了某些内容,或者我尝试反序列化列表的方式有什么问题?

如果我错过了重要的代码,请告诉我,我会根据其他需要进行更新。我还删掉了多余的部分,所以我可能在没有意识到的情况下剪了太多。

编辑: GetUser类(class):

<Serializable(), DataContract([Namespace]:="MyNamespace")> _
Public Class GetUser

<DataMember(Name:="UserName")> _
Public UserName As String
<DataMember(Name:="Password")> _
Public Password As String
End Class

编辑 #2:
在处理了反序列化器可能抛出的错误后,我发现反序列化过程正在抛出 UnknownNode异常后跟 UnknownElement第 21 行,位置 3 的异常。详细说明预期元素是“:TaskRequests”。

最佳答案

好的,我已经用 C# 重新实现了您的解决方案,不同之处在于您没有为 TaskRequests 提供命名空间。在 MobileRequest类。

总结一下:

1) 您混合了 DataContractSerializer 的属性和 XmlSerializer这使得这段代码难以管理,我只使用了 XmlSerializer相关属性。

2) 您提供的 XML 不能 是序列化您提供的类的结果。它在 TaskReqests 上包含“MyNameSpace”字段,而在您的代码中没有 XmlSerializer 的命名空间(仅适用于 DataContractSerializer,此处不相关)。

3)使您正确反序列化的代码的最小修复(请参阅下面的编辑)是:

[Serializable]
public class MobileRequest
{
[XmlArray(Namespace="MyNameSpace")] //note the namespace
public List<MobileTask> TaskRequests = new List<MobileTask>();

public MobileRequest()
{
TaskRequests = new List<MobileTask>();
}
}

(为了清楚起见,我还删除了 DataContractSerializer 属性)。
它是用 C# 编写的,但我希望你能很容易地发现不同之处 - 给 Namespace XmlArray 的参数属性。

可能有用的引用资料:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer%28v=vs.90%29.aspx

http://www.codeproject.com/Articles/14064/Using-the-XmlSerializer-Attributes

编辑:

事实证明,XmlSerializer 无法反序列化它自己序列化的内容!在以下代码之后使用上面定义的类和描述的修复:
XmlSerializer s = new XmlSerializer(typeof(MobileRequest));

MobileRequest mr = new MobileRequest();
mr.TaskRequests.Add(new MobileTask() { TaskID = 1, TaskType = MobileTask.TypesOfTasks.GetUser, TaskArgs = new Obj.GetUser() { Password = "test", UserName = "t" } });
mr.TaskRequests.Add(new MobileTask() { TaskID = 2, TaskType = MobileTask.TypesOfTasks.GetUser, TaskArgs = new Obj.GetUser() { Password = "test", UserName = "t2" } });

using (StreamWriter sw = new StreamWriter("test.txt"))
{
s.Serialize(sw, mr);
}

StreamReader sr = new StreamReader("test.txt");
XmlReader xmlReader = XmlReader.Create(sr);
XmlDeserializationEvents xde = new XmlDeserializationEvents();
xde.OnUnknownElement = new XmlElementEventHandler((o, e) =>
{
Console.WriteLine("Unknown element:" + e.Element.Name);
});
xde.OnUnknownNode = new XmlNodeEventHandler((o, e) =>
{
Console.WriteLine("Unknown node:" + e.Name);
});
var r = s.Deserialize(xmlReader, xde);
Console.ReadKey();
XmlNodes出现而不是 TaskArgs!删除所有命名空间定义和引用可以解决问题。我读过很多关于 XmlSerializer 的问题,尤其是命名空间的问题,所以如果可以的话,你可能想使用 DataContractSerializerNetDataContractSerializer如本主题中所建议: Why is XmlSerializer's Deserialize() spitting out a child object which is a XmlNode[]? .

关于xml - 反序列化对象列表产生空列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18365412/

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