Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Xml Serialization

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article shares with you the content of a sample analysis of Xml serialization. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

XML serialization is the process of converting the public properties and fields of an object into XML format for storage or transmission. Deserialization recreates the object in its original state from the XML output. The main class in XML serialization is the XmlSerializer class. Its most important methods are the Serialize and Deserialize methods, which are located in the System.Xml.Serialization namespace.

1. Basic points of XML serialization

Before we begin this section, let's look at the simplest example:

Namespace learning test {class Program {static void Main (string [] args) {Person p = new Person (1, "Liu Bei", 176); string xmlString = ""; / / xml serialization start using (MemoryStream ms = new MemoryStream ()) {Type t = p.GetType () XmlSerializer xml = new XmlSerializer (t); xml.Serialize (ms, p); byte [] arr = ms.ToArray (); xmlString = Encoding.UTF8.GetString (arr, 0, arr.Length); ms.Close ();} Console.WriteLine (xmlString); Console.ReadKey () }} public class Person {/ / must define a no-argument constructor, otherwise it cannot be serialized (of course, it can be serialized without writing the constructor at all, because there is a default no-parameter constructor) public Person () {} public Person (int id, string name, int age) {Id = id; Name = name / / Age = age;} public int Id {get; set;} public string Name {get; set;} / / Private field private int Age {get; set;} / / read-only attribute private int height; public int Height {get {return height;}

The code output is as follows:

From the above output, we can conclude that the no-parameter constructor must be required, and the default is fine. Note, however, that when the default no-parameter constructor is overridden, a no-parameter constructor is added. In addition, private properties, read-only properties cannot be serialized.

More caveats:

The class to be serialized must have a default constructor before you can use XmlSerializer serialization

Method cannot be serialized

Indexers, private fields, or read-only properties (except read-only collection properties) cannot be serialized

All classes that need to be serialized must have a no-argument constructor

Enumerated variables can be serialized into strings without the need for [XmlInclude]

The export of non-basic type objects must be declared in advance with [XmlInclude]. The rule recursively applies to child elements

If the IsNullable parameter in Attribute is equal to false, it means that if the element is null, the element is not displayed. (valid for value types)

Some classes simply cannot be serialized by XML (even if [XmlInclude] is used)

IDictionary (e.g. HashTable)

The case in which a parent object assigns a value to a subclass object

Circular references between objects

9. For objects that cannot be serialized by XML, consider

Use custom xml serialization (implement the IXmlSerializable interface)

For classes that implement IDictionary, consider (1) replacing them with other collection classes, (2) encapsulating them with classes, and providing Add and this functions

Some types need to be converted before they can be serialized into XML. If XML serializes System.Drawing.Color, you can first convert it to an integer with ToArgb ()

If it is inconvenient to serialize overly complex objects with xml, consider using binary serialization.

When you do not want to serialize:

When you do not want to serialize an attribute, use the [System.Xml.Serialization.XmlIgnore] tag, which can be used for attributes

[NonSerializable] is not valid for attributes and can be used for classes, structures, etc.

The default constructor is necessary because deserialization essentially uses reflection and requires a default constructor to instantiate the class. If you remove the default constructor, the compilation will be fine, but the run will report an error.

Try not to initialize large properties in the default constructor, which causes the list to be initialized twice during deserialization: once in the default constructor and once read from the XML document during deserialization.

Change the default value of XML serialization

In general, there are many things that are automatically generated during XML serialization, such as XML namespaces, coding, and so on.

1. Remove the default namespace and prefix:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces (); ns.Add ("", "); / / the first parameter is the prefix, the second parameter is the namespace / / and then, when serializing, specify the custom namespace xml.Serialize (ms, p, ns).

Output comparison:

Of course, this method can also be used to generate the custom namespace you want.

2. Remove the XML declaration: the

Public static string ObjectToXmlSerializer (Object Obj) {XmlWriterSettings settings = new XmlWriterSettings (); / / remove xml statement settings.OmitXmlDeclaration = true; settings.Encoding = Encoding.Default; System.IO.MemoryStream mem = new MemoryStream () Using (XmlWriter writer = XmlWriter.Create (mem, settings)) {/ / remove default namespaces xmlns:xsd and xmlns:xsi XmlSerializerNamespaces ns = new XmlSerializerNamespaces (); ns.Add ("", "); XmlSerializer formatter = new XmlSerializer (Obj.GetType ()); formatter.Serialize (writer, Obj, ns) } return Encoding.Default.GetString (mem.ToArray ());}

Output:

3. Newline indentation

Settings.Indent = true

When XmlWriterSettings is set in this way, the output XML is:

4. Specify indented characters

Settings.IndentChars = "-"

The output is as follows:

More XmlWriterSettings setting properties are as follows:

The member description CloseOutput gets or sets a value indicating whether XmlWriter should also close the underlying stream or TextWriter when the Close method is called. Encoding gets or sets the type of text encoding to use. Indent gets or sets a value indicating whether the element is indented. IndentChars gets or sets the string to use when indenting. NamespaceHandling gets or sets a value indicating whether XmlWriter should remove duplicate namespace declarations when writing XML content. Is the default for all namespace declarations that appear in the output program NewLineChars gets or sets the string NewLineHandling to use for line breaks gets or sets a value indicating whether to normalize line breaks in the output. NewLineOnAttributes gets or sets a value indicating whether the property is written to a new row. OmitXmlDeclaration gets or sets a value indicating that the XML declaration is omitted. Encoding gets or sets the type of text encoding to use. The Reset method resets the above properties

Http://msdn.microsoft.com/zh-cn/library/system.xml.xmlwritersettings(v=vs.110).aspx

3. Implement serialization interface IXmlSerializable

After implementing the IXmlSerializable interface, we can customize how the class is serialized.

The interface contains three methods:

XmlSchema GetSchema (); void ReadXml (XmlReader reader); void WriteXml (XmlWriter writer)

Simple example:

Namespace custom serialization {class Program {static void Main (string [] args) {Person p = new Person (); p.Id = 1; p.Name = "Liu Bei"; string str = ObjectToXmlSerializer (p); Console.WriteLine (str); Person p1 = ObjectToXmlDESerializer (str) Console.WriteLine ("my name is:" + p1.Name); Console.ReadKey ();} / serialize Xml public static string ObjectToXmlSerializer (Object Obj) {string XmlString = ""; XmlWriterSettings settings = new XmlWriterSettings (); / / remove the xml declaration / / settings.OmitXmlDeclaration = true; settings.Indent = true Settings.Encoding = Encoding.Default; using (System.IO.MemoryStream mem = new MemoryStream ()) {using (XmlWriter writer = XmlWriter.Create (mem, settings)) {/ / remove the default namespaces xmlns:xsd and xmlns:xsi XmlSerializerNamespaces ns = new XmlSerializerNamespaces () Ns.Add (","); XmlSerializer formatter = new XmlSerializer (Obj.GetType ()); formatter.Serialize (writer, Obj, ns);} XmlString = Encoding.Default.GetString (mem.ToArray ());} return XmlString } / / deserialize public static T ObjectToXmlDESerializer (string str) where T: class {object obj; using (System.IO.MemoryStream mem = new MemoryStream (Encoding.Default.GetBytes (str) {using (XmlReader reader = XmlReader.Create (mem)) {XmlSerializer formatter = new XmlSerializer (typeof (T)) Obj = formatter.Deserialize (reader);}} return obj as T;}} public class Person {public int Id {get; set;} public string Name {get; set;}} public class PersonSerializer: IXmlSerializable {private Person p; public int Id {get; set } public string Name {get; set;} # region IXmlSerializable member System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema () {throw new NotImplementedException ();} / if this method defaults, there is an error in the XML document (2,2). Void IXmlSerializable.ReadXml (XmlReader reader) {reader.ReadElementString ("Person");} void IXmlSerializable.WriteXml (XmlWriter writer) {writer.WriteElementString ("Id", Id.ToString ()); writer.WriteElementString ("Name", Name);} # endregion}}

The output is as follows:

As we all know, interfaces do not support serialization. Here's a useful example of serialization and deserialization of IList:

Serialization and deserialization of namespace IList {class Program {static void Main (string [] args) {Woman W1 = new Woman () {Id = 1, Name = "Diao Chan"}; Woman w2 = new Woman () {Id = 2, Name = "Xi Shi"}; List ListWoman = new List (); ListWoman.Add (w1) ListWoman.Add (w2); Person p = new Person (); p.Id = 1; p.Name = "Liu Bei"; p.ListWoman = ListWoman; string str = ObjectToXmlSerializer (p); Console.WriteLine (str); Person p1 = ObjectToXmlDESerializer (str) Console.WriteLine ("my name is: + p1.Name +" my wife has: "); foreach (Woman w in p1.ListWoman) {Console.WriteLine (w.Name);} Console.ReadKey () } / / serialize Xml public static string ObjectToXmlSerializer (Object Obj) {string XmlString = ""; XmlWriterSettings settings = new XmlWriterSettings (); / / remove xml declaration / / settings.OmitXmlDeclaration = true; settings.Indent = true; settings.Encoding = Encoding.Default Using (System.IO.MemoryStream mem = new MemoryStream ()) {using (XmlWriter writer = XmlWriter.Create (mem, settings)) {/ / remove the default namespaces xmlns:xsd and xmlns:xsi XmlSerializerNamespaces ns = new XmlSerializerNamespaces (); ns.Add (",") XmlSerializer formatter = new XmlSerializer (Obj.GetType ()); formatter.Serialize (writer, Obj, ns);} XmlString = Encoding.Default.GetString (mem.ToArray ());} return XmlString } / / deserialize public static T ObjectToXmlDESerializer (string str) where T: class {object obj; using (System.IO.MemoryStream mem = new MemoryStream (Encoding.Default.GetBytes (str) {using (XmlReader reader = XmlReader.Create (mem)) {XmlSerializer formatter = new XmlSerializer (typeof (T)) Obj = formatter.Deserialize (reader);}} return obj as T;}} public class Person: IXmlSerializable {public int Id {get; set;} public string Name {get; set;} public IList ListWoman {get; set } # region IXmlSerializable member System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema () {throw new NotImplementedException ();} void IXmlSerializable.ReadXml (XmlReader reader) {/ / be sure to pay special attention to the pairing problem, otherwise it is easy to deserialize the collection and only read the first reader.ReadStartElement ("Person") Id = Convert.ToInt32 (reader.ReadElementString ("Id")); Name = reader.ReadElementString ("Name"); / / I don't know why only one complex type can be defined. After obtaining the value, the original value is assigned to List ListWoman2 = new List (); reader.ReadStartElement ("ListWoman") While (reader.IsStartElement ("Woman")) {Woman w = new Woman (); reader.ReadStartElement ("Woman"); w.Id = Convert.ToInt32 (reader.ReadElementString ("Id")); w.Name = reader.ReadElementString ("Name"); reader.ReadEndElement (); reader.MoveToContent () ListWoman2.Add (w);} ListWoman = ListWoman2; reader.ReadEndElement (); reader.ReadEndElement ();} void IXmlSerializable.WriteXml (XmlWriter writer) {/ / here is the writer.WriteElementString that does not need WriteStart/End Person ("Id", Id.ToString ()) Writer.WriteElementString ("Name", Name); / / overloaded. To set the namespace, just add writer.WriteStartElement ("ListWoman") to the parameter; foreach (Woman item in ListWoman) {PropertyInfo [] ProArr = item.GetType (). GetProperties (); writer.WriteStartElement ("Woman") Foreach (PropertyInfo p in ProArr) {writer.WriteElementString (p.Name, p.GetValue (item, null). ToString ());} writer.WriteEndElement ();} writer.WriteEndElement ();} # endregion} public class Woman {public int Id {get; set } public string Name {get; set;}

The output is as follows:

The above code can be directly used to serialize arrays, that is, IList. Here are two methods for serializing and deserializing IList:

/ / serialize Xml public static string ListToXmlSerializer (IList ListT) {XmlSerializer ser = new XmlSerializer (ListT.GetType ()); System.IO.MemoryStream mem = new MemoryStream (); XmlWriterSettings settings = new XmlWriterSettings (); settings.Indent = true; settings.OmitXmlDeclaration = false; settings.Encoding = Encoding.UTF8; XmlWriter writer = XmlWriter.Create (mem, settings) Ser.Serialize (writer, ListT); writer.Close (); string strtmp = Encoding.UTF8.GetString (mem.ToArray ()); return strtmp;} / / deserialize Xml public static List XmlToListSerializer (Stream stream) {string XmlPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @ "\ OutLine\" + typeof (T). Name + ".xml" Using (StreamReader sr = new StreamReader (stream, System.Text.Encoding.UTF8)) {XmlSerializer ser = new XmlSerializer (typeof (List)); var listsch = ser.Deserialize (sr); List reses = listsch as List; return reses;}}

Here is an example of serializing and deserializing complex objects through reflection:

Using System.Linq.Expressions;namespace console _ learning test {class Program {static void Main (string [] args) {Woman W1 = new Woman () {Id = 1, Name = "Diao Chan"}; Woman w2 = new Woman () {Id = 2, Name = "Xi Shi"}; List ListWoman1 = new List (); ListWoman1.Add (w1) ListWoman1.Add (w2); List ListPerson = new List (); Person p1 = new Person () {Id = 1, Name = "Liu Bei", ListWoman = ListWoman1}; Person p2 = new Person () {Id = 2, Name = "Guan Yu", ListWoman = ListWoman1}; Person p3 = new Person () {Id = 3, Name = "Zhang Fei", ListWoman = ListWoman1} ListPerson.Add (p1); ListPerson.Add (p2); ListPerson.Add (p3); string xml = ListToXmlSerializer (ListPerson); Console.WriteLine (xml); MemoryStream mem = new MemoryStream (Encoding.UTF8.GetBytes (xml)); List ListPerson2 = XmlToListSerializer (mem); Console.WriteLine (ListPerson2.Count) Console.WriteLine (ListPerson2 [2] .ListWoman [1] .Name); Console.ReadKey ();} / / serialize Xml public static string ListToXmlSerializer (IList ListT) {XmlSerializer ser = new XmlSerializer (ListT.GetType ()); System.IO.MemoryStream mem = new MemoryStream (); XmlWriterSettings settings = new XmlWriterSettings (); settings.Indent = true Settings.OmitXmlDeclaration = true; settings.Encoding = Encoding.UTF8; XmlWriter writer = XmlWriter.Create (mem, settings); ser.Serialize (writer, ListT); writer.Close (); string strtmp = Encoding.UTF8.GetString (mem.ToArray ()); File.WriteAllText (@ "D:\ 222.xml", strtmp); return strtmp } / / deserialize Xml public static List XmlToListSerializer (Stream stream) {using (StreamReader sr = new StreamReader (stream, System.Text.Encoding.UTF8)) {XmlSerializer ser = new XmlSerializer (typeof (List)); var listsch = ser.Deserialize (sr); List reses = listsch as List; return reses Public class Person: IXmlSerializable {public int Id {get; set;} public string Name {get; set;} public IList ListWoman {get; set;} # region IXmlSerializable member System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema () {throw new NotImplementedException () } void IXmlSerializable.ReadXml (XmlReader reader) {/ / while (reader.Name = = "Person") / / {reader.ReadStartElement ("Person"); Id = Convert.ToInt32 (reader.ReadElementString ("Id")); Name = reader.ReadElementString ("Name"); List newWomans = new List () PropertyInfo [] ProArr = typeof (Woman). GetProperties (); reader.ReadStartElement ("ListWoman"); while (reader.IsStartElement ("Woman")) {Woman Item2 = new Woman (); reader.ReadStartElement ("Woman") Foreach (PropertyInfo p in ProArr) {string str = reader.ReadElementString (p.Name); p.SetValue (Item2, Convert.ChangeType (str, p.PropertyType), null);} reader.ReadEndElement (); reader.MoveToContent (); newWomans.Add (Item2) } ListWoman = newWomans; reader.ReadEndElement (); reader.ReadEndElement ();} void IXmlSerializable.WriteXml (XmlWriter writer) {writer.WriteElementString ("Id", Id.ToString ()); writer.WriteElementString ("Name", Name); writer.WriteStartElement ("ListWoman") Foreach (Woman item in ListWoman) {PropertyInfo [] ProArr = item.GetType () .GetProperties (); writer.WriteStartElement ("Woman") Foreach (PropertyInfo p in ProArr) {if (p.GetValue (item, null)! = null) {writer.WriteElementString (p.Name, p.GetValue (item, null). ToString ()) } else {writer.WriteElementString (p.Name, ");}} writer.WriteEndElement ();} writer.WriteEndElement () } # endregion} public class Woman {public int Id {get; set;} public string Name {get; set;}

The output of the above code:

As a special reminder, you must pay special attention to the problem of ReadStartElement and ReadEndElement, otherwise it is easy to read only the first one when deserializing the collection. For serialization, if WriteStartElement and WriteEndElement do not match, the only problem is the mismatch of XML tag pairs, which is not as bad as Read.

IV. XML characteristics

Sometimes when we want to customize the structure of the XML when serializing, it's time to use our property class. The property class provides many features for us to use to complete the custom serialization function.

The name description XmlAttribute represents a collection of property objects These objects control how XmlSerializer serializes and deserializes objects XmlArrayAttribute specifies that XmlSerializer should serialize specific class members to an array of XML elements XmlArrayItemAttribute specifies that XmlSerializer can be placed in a serialized array of derived types XmlArrayItemAttributes represents a collection of XmlArrayItemAttribute objects XmlAttributeAttribute specifies that XmlSerializer should serialize class members as XML attributes XmlChoiceIdentifierAttribute specifies that XmlElementAttribute can further disambiguate members when XmlSerializer serializes or deserializes containing objects Indicates that a public field or attribute represents a collection of XML elements XmlElementAttributes that XmlSerializer uses for its default way of overriding serialized classes XmlEnumAttribute controls how XmlSerializer serializes enumerated members XmlIgnoreAttribute instructs XmlSerializer methods not to serialize public fields or public read / write attribute values XmlIncludeAttribute allows XmlSerializer to recognize the type XmlRootAttribute controls XML serialization XmlTextAttribute as an attribute target of the XML root element when it serializes or deserializes objects Want XmlSerializer to indicate that this member should be treated as XML text XmlTypeAttribute controls the XML structure generated when the attribute target is serialized by XmlSerializer XmlAnyAttributeAttribute specified members (fields that return an array of XmlAttribute objects) can contain the XML attribute XmlAnyElementAttribute specified members can contain objects This object represents all XML elements that do not have corresponding members in a serialized or deserialized object XmlAnyElementAttributes represents a collection of XmlAnyElementAttribute objects XmlAttributeEventArgs provides data for UnKnowAttribute XmlAttributeOverrides allows you to override properties, fields, and class properties XmlElementEventArgs for UnknownElement events when serializing or deserializing using XmlSerializer, XmlNamespaceDeclarationsAttribute specifies target properties, parameters, The return value or class member contains a prefix associated with the namespace used in the XML document XmlNodeEventArgs provides data for UnknownNode time XmlSerializer serializes objects into XML documents and deserializes objects from XML documents XmlSerializer allows you to control how objects are encoded into XML XmlSerializerNamespaces contains XmlSerializer XML namespaces used to generate qualified names in XML document instances and the prefix XmlTypeMapping contains mappings from one type to another

Here are just two simple examples:

Namespace Learning Test {[Serializable] public class Person {public Person () {} public int Id {get; set;} public string Name {get; set;} [XmlAttribute (DataType = "string")] public string Content {get; set;} [XmlIgnore] public int Age {get; set } [XmlArray] [XmlArrayItem ("Int32", typeof (Int32))] public IList ListInt {get; set;}} class Program {static void Main (string [] args) {IList list = new ArrayList (); list.Add (1); list.Add (2); list.Add (3) Person p = new Person (); p.Id = 1; p.Name = "Liu Bei"; p.Age = 23; p.Content = "this is an awesome man"; p.ListInt = list; string strXml = ObjectToXmlSerializer (p); Console.WriteLine (strXml) / / there are still problems with deserialization IList / / Person p2 = ObjectToXmlDESerializer (strXml); / / Console.WriteLine (p2.Name); Console.ReadKey ();} / / serialization public static string ObjectToXmlSerializer (Object Obj) {string XmlString = "; XmlWriterSettings settings = new XmlWriterSettings () / / remove xml statement / / settings.OmitXmlDeclaration = true; settings.Indent = true; settings.Encoding = Encoding.Default Using (System.IO.MemoryStream mem = new MemoryStream ()) {using (XmlWriter writer = XmlWriter.Create (mem, settings)) {/ / remove the default namespaces xmlns:xsd and xmlns:xsi XmlSerializerNamespaces ns = new XmlSerializerNamespaces (); ns.Add (",") XmlSerializer formatter = new XmlSerializer (Obj.GetType ()); formatter.Serialize (writer, Obj, ns);} XmlString = Encoding.Default.GetString (mem.ToArray ());} return XmlString } / / deserialize Xml public static T ObjectToXmlDESerializer (string str) where T: class {object obj; using (System.IO.MemoryStream mem = new MemoryStream (Encoding.Default.GetBytes (str) {using (XmlReader reader = XmlReader.Create (mem)) {XmlSerializer formatter = new XmlSerializer (typeof (T)) Obj = formatter.Deserialize (reader);}} return obj as T;}}

2013-12-27 frequently encountered error record:

Deserialization error prompt:

1. There is an error in the XML document (2,2):

This error is generally reported because the types of serialization and deserialization are not consistent:

XmlSerialize.Serialize (@ "C:\ Person.xml", person); / / person is the object of the Person class var test = XmlSerialize.DeSerialize (typeof (Person), @ "C:\ Person.xml")

2014-08-12

2. The difference between XmlIgnore and NonSerialized.

1. XmlIgnore can act on attributes, while NonSerialized can only act on fields.

2. XmlIgnore is effective for both serialization and deserialization, while NonSerialized only affects serialization, regardless of deserialization. (not 100% sure)

Thank you for reading! This is the end of this article on "sample analysis of Xml serialization". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 225

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report