作者
喵叔
责编
刘静
今天我利用这篇文章给大家讲解一下C#中的序列化与反序列化。这两个概念我们在开发中经常用到,但是我们绝大部分只用到了其中的一部分,剩下的部分很多开发人员并不清楚,伸着可以说是不知道。因此我希望通过这篇文章能让各位对序列化和反序列化的知识有更进一步的掌握。废话不多说开始进入正题。
什么是序列化/反序列化
在所有的开发语言中都存在序列化和反序列化这个概念,所谓的序列化就是把一个对象信息转化为一个可以持久存储的数据形式,经过转化后就可以方便的保存和传输了,因此序列化主要用于平台之间的通讯。由序列化我们可以反推出所谓的反序列化就是将持久存储的数据还原为对象。
C#中的序列化/反序列化
在C#中我们经常会对JSON和XML进行序列化和反序列化,但是还有存在一种序列化/反序列化,那就是将对象序列化为二进制文件,将会二进制文件反序列化为对象。下面我将会对这三种序列化和反序列化进行讲解。
1.JSON
JSON的英文全称是JavaScriptObjectNotation,是一种轻量级的数据交换格式。完全独立于语言的文本格式易于人阅读和编写同时也易于机器解析和生成。JSON是目前互联网中主流的数据交换格式,同时也是很多开发语言配置文件的主流格式。
在.NET中存在两个类对JSON进行处理,分别是DataContractJsonSerializer和JavaScriptSerializer,这两个类的功能基本一致。DataContractJsonSerializer位于命名空间System.Runtime.Serialization.Json下,它的特点是必须使用DataContract以及DataMember属性标记成员。JavaScriptSerializer位于命名空间System.Web.Script.Serialization下,通过名字和它所在的命名空间我们可以得知它主要用在网络通信中,它可以序列化任何类型的对象。同样.NET中也存在一个强大的第三方JSON序列化/反序列化库Newtonsoft.Json,他比前两个类用起来要方便很多。下面我们对这三个序列化/反序列化的方式分别进行讲解。
DataContractJsonSerializer首先我们需要在项目中引用DataContractJsonSerializer所在的命名空间,这里要注意的时我们不仅要在项目中添加引用System.Runtime.Serialization还需要添加引用System.ServiceModel.Web。将这两个命名空添加到命名空间后就可以在代码中引入DataContractJsonSerializer的命名空间了。
usingSystem.Runtime.Serialization;usingSystem.Runtime.Serialization.Json;
引入命名空间后我们开始编写序列化类
[DataContract]classStudent{[DataMember]publicstringName{get;set;}[DataMember]publicintSex{get;set;}[DataMember]publicintAge{get;set;}[DataMember]publicAddressAddress{get;set;}}[DataContract]classAddress{[DataMember]publicstringCity{get;set;}[DataMember]publicstringRoad{get;set;}}
在上述代码中我们看到在类的头部添加了DataContract特性,以及在类的属性上也增加了DataMember特性。一旦一个类被声明为DataContract时就代表着该类可以被序列化,并且可以在服务端和客户端传输。只有声明为DataContract的类型的对象可以被传送,且只有成员属性会被传递,成员方法不会被传递。默认情况下类中的所有成员属性都不会被序列化传输出去,如果需要将成员数据传输出去就需要在属性头部加入DataMember。
下面我们就利用DataContractJsonSerializer对对象尽心序列化和反序列化,代码如下
classProgram{staticvoidMain(string[]args){#region对象转JSON字符串Studentstudent=newStudent{Name=Tom,Age=20,Sex=1,Address=newAddress{City=NYC,Road=ABC}};//利用WriteObject方法序列化为JSONDataContractJsonSerializerserializer=newDataContractJsonSerializer(typeof(Student));MemoryStreamstream=newMemoryStream();serializer.WriteObject(stream,student);byte[]bytes=newbyte[stream.Length];stream.Position=0;stream.Read(bytes,0,(int)stream.Length);stringjsonStr=Encoding.UTF8.GetString(bytes);Console.WriteLine(jsonStr);#endregion#regionJSON字符串转对象stream=newMemoryStream(Encoding.Default.GetBytes(jsonStr));student=(Student)serializer.ReadObject(stream);Console.WriteLine(Namestudent.Name);Console.WriteLine(Sexstudent.Sex);Console.WriteLine(Agestudent.Age);Console.WriteLine(Addressstudent.Address.City++student.Address.Road);#endregionConsole.ReadLine();}}
输出结果如下:
JavaScriptSerializer我们利用前面定义的类,来看一下JavaScriptSerializer的使用方法,我们将前面定义的类中的DataContract和DataMember都去掉。我们如果要使用JavaScriptSerializer只需引入System.Web.Script.Serialization命名空间即可。代码如下:
usingSystem.Web.Script.Serialization;
下面我们就利用JavaScriptSerializer对象进行序列化和反序列化,代码如下:
classProgram{staticvoidMain(string[]args){#region序列化Studentstudent=newStudent{Name=Tom,Age=20,Sex=1,Address=newAddress{City=NYC,Road=ABC}};//初始化JavaScriptSerializerserializer=newJavaScriptSerializer();stringjsonStr=serializer.Serialize(student);Console.WriteLine(jsonStr);#endregion#region反序列化student=serializer.DeserializeStudent(jsonStr);Console.WriteLine(Namestudent.Name);Console.WriteLine(Sex:+student.Sex);Console.WriteLine(Age:+student.Age);Console.WriteLine(Address:+student.Address.City++student.Address.Road);#endregionConsole.ReadLine();}}
从上面的代码我们可以看出利用JavaScriptSerializer序列化和反序列化要比DataContractJsonSerializer类方便。上述代码运行结果如下:
Newtonsoft.JsonNewtonsoft.Json功能有很多,除了序列化反序列化之外,还有LinqToJson、JsonPath、XMLsupport等,我们这篇文章我们只讲解其中的序列化和反序列化。使用Newtonsoft.Json前首先我们需要在nuget中搜索并安装,安装完成后引入Newtonsoft.Json,代码如下:
usingNewtonsoft.Json;
下面我们来看看Newtonsoft.Json的具体使用:
classProgram{staticvoidMain(string[]args){#region序列化Studentstudent=newStudent{Name=Tom,Age=20,Sex=1,Address=newAddress{City=NYC,Road=ABC}};stringjsonStr=JsonConvert.SerializeObject(student);Console.WriteLine(jsonStr);#endregion#region反序列化student=JsonConvert.DeserializeObjectStudent(jsonStr);Console.WriteLine(Name:+student.Name);Console.WriteLine(Sex:+student.Sex);Console.WriteLine(Age:+student.Age);Console.WriteLine(Address:+student.Address.City++student.Address.Road);#endregionConsole.ReadLine();}}
上述代码输出结果如下:
从代码中我们看到Newtonsoft.Json序列化和反序列化更加简单,简单到只需要一行代码就完成了序列化和反序列化。
2.XML
在JSON还没出现之前,XML是互联网上常用的数据交换格式和规范。.NET中提供XmlSerializer类将对象序列化为XML和将XML反序列化为对象,使用方法是首先实例化,然后调用序列化/反序列化方法。下面我们依然使用最开始定义的那个类,来看看XmlSerializer的使用。使用前我们需要引入usingSystem.Xml.Serialization命名空间。
usingSystem.Xml.Serialization;
具体序列化/反序列化方法如下:
classProgram{staticvoidMain(string[]args){#region序列化Studentstudent=newStudent{Name=Tom,Age=20,Sex=1,Address=newAddress{City=NYC,Road=ABC}};XmlSerializerxmlSerializer=newXmlSerializer(typeof(Student));using(FileStreamstream=newFileStream(
d:\.xml,FileMode.OpenOrCreate)){xmlSerializer.Serialize(stream,student);}#endregion#region反序列化using(FileStreamstream=newFileStream(d:\.xml,FileMode.OpenOrCreate)){XmlReaderxmlReader=newXmlTextReader(stream);student=xmlSerializer.Deserialize(xmlReader)asStudent;}Console.WriteLine(Name:+student.Name);Console.WriteLine(Sex:+student.Sex);Console.WriteLine(Age:+student.Age);Console.WriteLine(Address:+student.Address.City++student.Address.Road);#endregionConsole.ReadLine();}}
这里有一点需要注意,如果对象类的访问修饰符不是public将会报错。上述代码运行结果如下:
3.二进制
序列化为二进制,在实际开发中真的很少用到,但是我觉得还是有必要讲一讲,它的使用方法和XmlSerializer序列化/反序列化类似,首先实例化,然后调用序列化/反序列化方法。在进行序列化/反序列化前首先引入命名空间System.Runtime.Serialization.Formatters.Binary,同时修改对象类如下:
[Serializable]publicclassStudent{publicstringName{get;set;}publicintSex{get;set;}publicintAge{get;set;}publicAddressAddress{get;set;}}[Serializable]publicclassAddress{publicstringCity{get;set;}publicstringRoad{get;set;}}
上述代码中我们在类的头部加入了Serializable特性,这代表着整个类对象都需要序列化,如果我们不需要序列化其中某个属性的话只需在该属性上加上NonSerialized特性即可。下面我们来看一下序列化和反序列化的代码:
classProgram{staticvoidMain(string[]args){#region序列化Studentstudent=newStudent{Name=Tom,Age=20,Sex=1,Address=newAddress{City=NYC,Road=ABC}};BinaryFormatterbinFormat=newBinaryFormatter();stringfileName=Path.Combine(
D:\,.txt);using(StreamfStream=newFileStream(fileName,FileMode.Create,FileAccess.ReadWrite)){binFormat.Serialize(fStream,student);}#endregion#region反序列化using(StreamfStream=newFileStream(fileName,FileMode.Open,FileAccess.ReadWrite)){fStream.Position=0;student=(Student)binFormat.Deserialize(fStream);}Console.WriteLine(Name:+student.Name);Console.WriteLine(Sex:+student.Sex);Console.WriteLine(Age:+student.Age);Console.WriteLine(Address:+student.Address.City++student.Address.Road);#endregionConsole.ReadLine();}}
上述代码最终输出结果如下:
总结
这篇文章详细讲解了.NET中序列化和反序列化相关知识的使用,序列化和反序列化相关的只是还有很多,这里所讲解的都是开发中经常用到的,也是面试过程中会提及的,因此大家需要牢记。
作者简介:朱钢,笔名喵叔,CSDN博客专家,.NET高级开发工程师,7年一线开发经验,参与过电子*务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司,从事企业级安全监控系统的开发。
声明:本文系作者独立观点,不代表CSDN立场。