[英]XML not deserializing to correct class, and not serializing with xsi:type attribute after
在以下代碼段中,我嘗試反序列化在Animal
記錄上具有類型屬性的XML,以將它們標識為Cat
或Dog
,這兩個屬性均繼承自Animal
。
反序列化時,這些記錄都顯示為Animal
。
然后,當嘗試序列化對象時(反序列化之后), xsi:type="Dog"
和xsi:type="Cat"
不會出現在XML中。
我不確定這是由於我裝飾類的方式還是在序列化器/反序列化器實現中。 如果可能的話,最好選擇類中的解決方案,而不要選擇序列化器/解串器包裝器方法。
碼:
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace sandbox
{
public partial class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<OuterClass xmlns=\"http://myschema.com/\">" +
" <Animals>" +
" <Animal xmlns:xsi=\"http://myschema.com/\" xsi:type=\"Dog\">" +
" <Name>Watson</Name>" +
" <Height>10</Height>" +
" <Weight>10</Weight>" +
" <Paws>4</Paws>" +
" <Woof>True</Woof>" +
" </Animal>" +
" <Animal xmlns:xsi=\"http://myschema.com/\" xsi:type=\"Cat\">" +
" <Name>Hermy</Name>" +
" <Height>10</Height>" +
" <Weight>10</Weight>" +
" <Paws>4</Paws>" +
" <Meow>True</Meow>" +
" </Animal>" +
" </Animals>" +
"</OuterClass>";
OuterClass data = null;
try
{
data = DeserializeXml<OuterClass>(xml);
foreach (Animal curr in data.Animals) Console.WriteLine(curr.Name + ": " + curr.GetType().ToString());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine(e.Message);
}
Console.WriteLine(SerializeXml(data));
Console.ReadLine();
}
public static T DeserializeXml<T>(string xml)
{
XmlSerializer xmls = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
return (T)xmls.Deserialize(ms);
}
public static string SerializeXml(object obj)
{
XmlSerializer xml = new XmlSerializer(obj.GetType());
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8))
{
xml.Serialize(writer, obj);
byte[] bytes = stream.ToArray();
return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
}
}
}
[XmlRoot(ElementName = "OuterClass", Namespace = "http://myschema.com/", IsNullable = true)]
public class OuterClass
{
[XmlArrayItem(Type = typeof(Cat)), XmlArrayItem(Type = typeof(Dog)), XmlArrayItem(Type = typeof(Animal))]
public Animal[] Animals { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
}
[XmlType(TypeName = "Cat")]
[XmlRoot(ElementName = "Animal", Namespace = "http://myschema.com/", IsNullable = true)]
public class Cat : Animal
{
public bool Meow { get; set; }
}
[XmlType(TypeName = "Dog")]
[XmlRoot(ElementName = "Animal", Namespace = "http://myschema.com/", IsNullable = true)]
public class Dog : Animal
{
public bool Woof { get; set; }
}
[XmlInclude(typeof(Cat))]
[XmlInclude(typeof(Dog))]
[XmlRoot(ElementName = "Animal", Namespace = "http://myschema.com/", IsNullable = true)]
public class Animal
{
public string Name { get; set; }
public int Height { get; set; }
public int Weight { get; set; }
public int Paws { get; set; }
}
}
輸出:
Watson: sandbox.Animal <-- should be sandbox.Dog
Hermy: sandbox.Animal <-- should be sandbox.Cat
?<?xml version="1.0" encoding="utf-8"?>
<OuterClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://myschema.com/">
<Animals>
<Animal> <-- missing xsi:type, object missing 'Woof'
<Name>Watson</Name>
<Height>10</Height>
<Weight>10</Weight>
<Paws>4</Paws>
</Animal>
<Animal> <-- missing xsi:type, object missing 'Meow'
<Name>Hermy</Name>
<Height>10</Height>
<Weight>10</Weight>
<Paws>4</Paws>
</Animal>
</Animals>
</OuterClass>
您需要正確創建類:
OuterClass outerClass = new OuterClass()
{
Animals = new Animal[] {
new Dog() { Name = "Watson", Height = 10, Weight = 10, Paws = 4},
new Cat() { Name = "Hermy", Height = 10, Weight = 10, Paws = 4}
}
};
您的示例中有兩個問題:
請在下面找到有關問題的其他詳細信息:
當您指定XmlArrayItem時, XmlSerializer
將使用類型名稱作為元素名稱,或者您可以通過顯式提供ElementName進行更改。 如果使用XmlArrayItem
注釋數組屬性,將得到以下輸出:
Console.WriteLine(SerializeXml(new OuterClass { Animals = new Animal[] { new Cat(), new Dog() } }));
<OuterClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://myschema.com/">
<Animals>
<Cat>
<Height>0</Height>
<Weight>0</Weight>
<Paws>0</Paws>
<Meow>false</Meow>
</Cat>
<Dog>
<Height>0</Height>
<Weight>0</Weight>
<Paws>0</Paws>
<Woof>false</Woof>
</Dog>
</Animals>
</OuterClass>
如果不加注釋,則將獲得由xsi:type屬性定義的類型的輸出:
<OuterClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://myschema.com/">
<Animals>
<Animal xsi:type="Cat">
<Height>0</Height>
<Weight>0</Weight>
<Paws>0</Paws>
<Meow>false</Meow>
</Animal>
<Animal xsi:type="Dog">
<Height>0</Height>
<Weight>0</Weight>
<Paws>0</Paws>
<Woof>false</Woof>
</Animal>
</Animals>
</OuterClass>
在這種情況下,您必須將XmlInclude
屬性添加到基類。
http://www.w3.org/2001/XMLSchema-instance是W3C中定義的特殊名稱空間,可幫助序列化程序了解XML元素中的類型。 在您的輸入xml中,每個Animal元素都會使用自定義http://myschema.com/覆蓋此命名空間,因此當序列化程序遇到xsi:type="Cat"
它根本不知道它的含義。 Wikipedia是閱讀XML命名空間的一個很好的起點: https : //en.wikipedia.org/wiki/XML_namespace
W3C將布爾數據類型定義為“ true”,“ false”,“ 0”和“ 1”,因此,如果將值“ T rue”反序列化布爾值,則會出現異常。 您可能會在網上找到解決方法選項,但我想您輸入的XML格式錯誤,因此您需要將XML中的布爾值小寫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.