開發者應當熟知的 C# 序列化和反序列化

開發者應當熟知的 C# 序列化和反序列化

作者 | 喵叔

出品 | CSDN(ID:CSDNnews)

今天我利用這篇文章給大家講解一下 C# 中的序列化與反序列化。這兩個概念我們在開發中經常用到,但是我們絕大部分只用到了其中的一部分,剩下的部分很多開發人員並不清楚,伸著可以說是不知道。因此我希望通過這篇文章能讓各位對序列化和反序列化的知識有更進一步的掌握。廢話不多說開始進入正題。

开发者应当熟知的 C# 序列化和反序列化

什麼是序列化/反序列化

在所有的開發語言中都存在序列化和反序列化這個概念,所謂的序列化就是把一個對象信息轉化為一個可以持久存儲的數據形式,經過轉化後就可以方便的保存和傳輸了,因此序列化主要用於平臺之間的通訊。由序列化我們可以反推出所謂的反序列化就是將持久存儲的數據還原為對象。

开发者应当熟知的 C# 序列化和反序列化

C# 中的序列化/反序列化

在 C# 中我們經常會對 JSON 和 XML 進行序列化和反序列化 ,但是還有存在一種序列化/反序列化,那就是將對象序列化為二進制文件,將會二進制文件反序列化為對象。下面我將會對這三種序列化和反序列化進行講解。

1. JSON

JSON 的英文全稱是 JavaScript Object Notation ,是一種輕量級的數據交換格式。完全獨立於語言的文本格式 易於人閱讀和編寫同時也易於機器解析和生成。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 的命名空間了。

<code>using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
/<code>

引入命名空間後我們開始編寫序列化類

<code>[DataContract]
class Student
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Sex { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public Address Address { get; set; }
}
[DataContract]
class Address
{
[DataMember]
public string City { get; set; }
[DataMember]
public string Road { get; set; }
}
/<code>

在上述代碼中我們看到在類的頭部添加了 DataContract 特性,以及在類的屬性上也增加了 DataMember 特性 。一旦一個類被聲明為 DataContract 時就代表著該類可以被序列化,並且可以在服務端和客戶端傳輸。只有聲明為DataContract的類型的對象可以被傳送,且只有成員屬性會被傳遞,成員方法不會被傳遞。默認情況下類中的所有成員屬性都不會被序列化傳輸出去,如果需要將成員數據傳輸出去就需要在屬性頭部加入 DataMember 。

下面我們就利用 DataContractJsonSerializer 對對象盡心序列化和反序列化,代碼如下

<code>class Program
{
static void Main(string[] args)
{
#region 對象轉JSON字符串
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
//利用WriteObject方法序列化為 JSON
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Student));
MemoryStream stream = new MemoryStream;
serializer.WriteObject(stream, student);
byte bytes=new byte[stream.Length];
stream.Position = 0;
stream.Read(bytes, 0, (int)stream.Length);
string jsonStr = Encoding.UTF8.GetString(bytes);
Console.WriteLine(jsonStr);
#endregion

#region JSON字符串轉對象
stream = new MemoryStream(Encoding.Default.GetBytes(jsonStr));
student = (Student)serializer.ReadObject(stream);
Console.WriteLine("Name: " +student.Name);
Console.WriteLine("Sex: " + student.Sex);
Console.WriteLine("Age: " + student.Age);
Console.WriteLine("Address: " + student.Address.City+" "+student.Add
ress.Road);
#endregion
Console.ReadLine;
}
}
/<code>

輸出結果如下:

开发者应当熟知的 C# 序列化和反序列化
  • JavaScriptSerializer

我們利用前面定義的類,來看一下 JavaScriptSerializer 的使用方法,我們將前面定義的類中的 DataContract 和 DataMember 都去掉。我們如果要使用 JavaScriptSerializer 只需引入 System.Web.Script.Serialization 命名空間即可。代碼如下:

<code>using System.Web.Script.Serialization; 

/<code>

下面我們就利用 JavaScriptSerializer 對象進行序列化和反序列化,代碼如下:

<code>class Program
{
static void Main(string[] args)
{
#region 序列化
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
//初始化
JavaScriptSerializer serializer = new JavaScriptSerializer;
string jsonStr = serializer.Serialize(student);
Console.WriteLine(jsonStr);
#endregion

#region 反序列化
student = serializer.Deserialize<student>(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);
#endregion
Console.ReadLine;
}
}
/<student>/<code>

從上面的代碼我們可以看出利用 JavaScriptSerializer 序列化和反序列化要比 DataContractJsonSerializer 類方便。上述代碼運行結果如下:

开发者应当熟知的 C# 序列化和反序列化
  • Newtonsoft.Json

Newtonsoft.Json 功能有很多,除了序列化反序列化之外,還有 Linq To Json、Json Path、 XML support等,我們這篇文章我們只講解其中的序列化和反序列化。使用 Newtonsoft.Json 前首先我們需要在 nuget 中搜索並安裝,安裝完成後引入 Newtonsoft.Json,代碼如下:

<code>using Newtonsoft.Json;
/<code>

下面我們來看看 Newtonsoft.Json 的具體使用:

<code>class Program
{
static void Main(string[] args)
{
#region 序列化
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
string jsonStr = JsonConvert.SerializeObject(student);
Console.WriteLine(jsonStr);
#endregion

#region 反序列化
student = JsonConvert.DeserializeObject<student>(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);
#endregion

Console.ReadLine;
}
}
/<student>/<code>

上述代碼輸出結果如下:

开发者应当熟知的 C# 序列化和反序列化

從代碼中我們看到 Newtonsoft.Json 序列化和反序列化更加簡單,簡單到只需要一行代碼就完成了序列化和反序列化。

2. XML

在 JSON 還沒出現之前,XML 是互聯網上常用的數據交換格式和規範。.NET 中提供 XmlSerializer 類將對象序列化為 XML 和將 XML 反序列化為對象,使用方法是首先實例化,然後調用序列化/反序列化方法。下面我們依然使用最開始定義的那個類,來看看 XmlSerializer 的使用。使用前我們需要引入 using System.Xml.Serialization 命名空間。

<code>using System.Xml.Serialization;
/<code>

具體序列化/反序列化方法如下:

<code>class Program
{
static void Main(string[] args)
{
#region 序列化
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student));
using (FileStream stream = new FileStream(@"d:\\123.xml", FileMode.OpenOrCreate))
{
xmlSerializer.Serialize(stream, student);
}
#endregion

#region 反序列化
using (FileStream stream = new FileStream(@"d:\\123.xml", FileMode.OpenOrCreate))
{
XmlReader xmlReader = new XmlTextReader(stream);
student = xmlSerializer.Deserialize(xmlReader) as Student;
}
Console.WriteLine("Name: " + student.Name);
Console.WriteLine("Sex: " + student.Sex);
Console.WriteLine("Age: " + student.Age);
Console.WriteLine("Address: " + student.Address.City + " " + student.Address.Road);
#endregion

Console.ReadLine;
}
}
/<code>

這裡有一點需要注意,如果對象類的訪問修飾符不是 public 將會報錯。上述代碼運行結果如下:

开发者应当熟知的 C# 序列化和反序列化开发者应当熟知的 C# 序列化和反序列化

3. 二進制

序列化為二進制,在實際開發中真的很少用到,但是我覺得還是有必要講一講,它的使用方法和 XmlSerializer 序列化/反序列化類似,首先實例化,然後調用序列化/反序列化方法。在進行序列化/反序列化前首先引入命名空間 System.Runtime.Serialization.Formatters.Binary ,同時修改對象類如下:

<code>[Serializable]
public class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
[Serializable]
public class Address
{
public string City { get; set; }
public string Road { get; set; }
}
/<code>

上述代碼中我們在類的頭部加入了 Serializable 特性,這代表著整個類對象都需要序列化,如果我們不需要序列化其中某個屬性的話只需在該屬性上加上 NonSerialized 特性即可。下面我們來看一下序列化和反序列化的代碼:

<code>class Program
{
static void Main(string[] args)

{
#region 序列化
Student student = new Student
{
Name = "Tom",
Age = 20,
Sex = 1,
Address = new Address
{
City = "NYC",
Road = "ABC"
}
};
BinaryFormatter binFormat = new BinaryFormatter;
string fileName = Path.Combine(@"D:\\", @"321.txt");
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
binFormat.Serialize(fStream, student);
}
#endregion

#region 反序列化
using (Stream fStream = new FileStream(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);
#endregion

Console.ReadLine;
}
}
/<code>

上述代碼最終輸出結果如下:

开发者应当熟知的 C# 序列化和反序列化开发者应当熟知的 C# 序列化和反序列化

總結

這篇文章詳細講解了.NET中序列化和反序列化相關知識的使用,序列化和反序列化相關的只是還有很多,這裡所講解的都是開發中經常用到的,也是面試過程中會提及的,因此大家需要牢記。

作者簡介:朱鋼,筆名喵叔,CSDN博客專家,.NET高級開發工程師,7年一線開發經驗,參與過電子政務系統和AI客服系統的開發,以及互聯網招聘網站的架構設計,目前就職於北京恆創融慧科技發展有限公司,從事企業級安全監控系統的開發。

聲明:本文系作者獨立觀點,不代表CSDN立場。

【END】


分享到:


相關文章: