如何在 C# 中序列化对象数组
本文关键字:序列化 对象 数组 | 更新日期: 2023-09-27 18:36:50
我用xsd.exe用这个xml文件生成了一个c#类:
<?xml version="1.0" encoding="UTF-8"?>
<Mary>
<Frank>
<Joe>
<Susan>
<Stuff>data</Stuff>
</Susan>
<Susan>
<Stuff>data</Stuff>
</Susan>
</Joe>
<Joe>
<Susan>
<Stuff>data</Stuff>
</Susan>
<Susan>
<Stuff>data</Stuff>
</Susan>
</Joe>
</Frank>
</Mary>
可以在此处查看生成的 C# 类。
我可以用数据初始化对象:
var susan = new MaryFrankJoeSusan(){Stuff = "my data"};
var frank = new MaryFrank(){Joe = new MaryFrankJoeSusan[1][]};
frank.Joe[0] = new MaryFrankJoeSusan[1]{susan};
var mary = new Mary { Items = new MaryFrank[1] { frank } };
我正在使用以下内容将其序列化到磁盘:
var serializer = new XmlSerializer(typeof(Mary));
using (Stream stream = new FileStream(@"C:'out.xml", FileMode.Create))
{
var settings = new XmlWriterSettings { Indent = true, NewLineOnAttributes = true, OmitXmlDeclaration = true};
using (XmlWriter writer = new XmlTextWriter(stream, Encoding.Unicode))
{
serializer.Serialize(writer, mary);
writer.Close();
}
}
但是,初始化序列化程序时出现以下错误:
error CS0030: Cannot convert type 'MaryFrankJoeSusan[]' to 'MaryFrankJoeSusan'
如何将整个 Mary 对象序列化到磁盘?
那些生成的类有些不对劲。
出现问题是因为MaryFrank.Joe
被声明为MaryFrankJoeSusan
对象的二维数组,但它用一个XmlArrayItemAttribute
装饰,该告诉序列化程序该 2D 数组的每个项目都是类型 MaryFrankJoeSusan
当它们当然是MaryFrankJoeSusan[]
时。
如果在生成的类中更改此行:
[System.Xml.Serialization.XmlArrayItemAttribute("Susan", typeof(MaryFrankJoeSusan),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
对此:
[System.Xml.Serialization.XmlArrayItemAttribute("Susan", typeof(MaryFrankJoeSusan[]),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
然后它将序列化而不会出错。 但是,您将无法获得所需的结果。 取而代之的是:
<Mary>
<Frank>
<Joe>
<Susan>
<Stuff>my data</Stuff>
</Susan>
</Joe>
</Frank>
</Mary>
你会得到这个(注意额外的MaryFrankJoeSusan
标签):
<Mary>
<Frank>
<Joe>
<Susan>
<MaryFrankJoeSusan>
<Stuff>my data</Stuff>
</MaryFrankJoeSusan>
</Susan>
</Joe>
</Frank>
</Mary>
真正的问题似乎是xsd.exe
工具一开始就错误地生成了类结构。 它不是在继承制中创建一个类来代表乔,而是试图将乔和苏珊组合在一起,这在这里并不奏效。
我通过该工具运行了问题中的原始 XML 以生成 XSD 架构,我得到了这个:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Mary" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Mary" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Frank">
<xs:complexType>
<xs:sequence>
<xs:element name="Joe" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Susan" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Stuff" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
这对我来说看起来还可以。 然后,我采用了相同的架构,并再次通过该工具运行它以生成 C# 类。 我本来希望得到类似的东西:
[Serializable]
[XmlRoot(Namespace = "", ElementName = "Mary")]
public class Mary
{
[XmlElement("Frank")]
public Frank[] Frank { get; set; }
}
[Serializable]
public class Frank
{
[XmlElement("Joe")]
public Joe[] Joe { get; set; }
}
[Serializable]
public class Joe
{
[XmlElement("Susan")]
public Susan[] Susan { get; set; }
}
[Serializable]
public class Susan
{
[XmlElement("Stuff")]
public string Stuff { get; set; }
}
但相反,我得到了您在问题中链接的相同损坏的类。 所以对我来说,它看起来像是 xsd 工具中的一个错误。
要使其工作,您可以使用我上面创建的手动编码类,将初始化代码更改为:
var susan = new Susan { Stuff = "my data" };
var joe = new Joe { Susan = new Susan[] { susan } };
var frank = new Frank { Joe = new Joe[] { joe } };
var mary = new Mary { Frank = new Frank[] { frank } };
--或--
另一种选择是更改 XSD。 将Frank
和Joe
元素的xs:sequence
指示器替换为xs:choice
,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Mary" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="Mary" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Frank">
<xs:complexType>
<xs:choice> <!-- was xs:sequence -->
<xs:element name="Joe" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:choice> <!-- was xs:sequence -->
<xs:element name="Susan" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Stuff" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice> <!-- was /xs:sequence -->
</xs:complexType>
</xs:element>
</xs:choice> <!-- was /xs:sequence -->
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
有了这个模式,生成的类就好多了:现在有一个类来表示 Joe。 (为了简洁起见,我在这里简化了生成的代码并删除了一些属性):
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class Mary {
[System.Xml.Serialization.XmlElementAttribute("Frank", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrank[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrank {
[System.Xml.Serialization.XmlElementAttribute("Joe", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrankJoe[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrankJoe {
[System.Xml.Serialization.XmlElementAttribute("Susan", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public MaryFrankJoeSusan[] Items { get; set; }
}
[System.SerializableAttribute()]
public partial class MaryFrankJoeSusan {
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Stuff { get; set; }
}
然后,设置代码变为:
var susan = new MaryFrankJoeSusan() { Stuff = "my data" };
var joe = new MaryFrankJoe() { Items = new MaryFrankJoeSusan[] { susan } };
var frank = new MaryFrank() { Items = new MaryFrankJoe[] { joe } };
var mary = new Mary { Items = new MaryFrank[] { frank } };
我们得到了预期的输出:
<?xml version="1.0" encoding="utf-16"?>
<Mary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Frank>
<Joe>
<Susan>
<Stuff>my data</Stuff>
</Susan>
</Joe>
</Frank>
</Mary>