今天我利用这篇文章给大家讲解一下C#中的序列化与反序列化。这两个概念我们再开发中经常用到,但是我们绝大部分只用到了其中的一部分,剩下的部分很多开发人员并不清楚,甚至可以说是不知道。因此我希望通过这篇文章能让大家对序列化和反序列化的知识有更进一步的掌握。废话不多说,开始进入正题。

一、什么是序列化/反序列化

在所有的开发语言中都存在序列化和反序列化这个概念,所谓的序列化就是把一个对象信息转化为一个可以持久存储的数据形式,经过转化后就可以方便的保存和传输了,因此序列化主要用于平台之间的通讯。由于序列化我们可以反推出所谓的反序列化就是将持久存储的数据还原为对象。

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

在C#中我们经常会对Json和Xml进行序列化和反序列化,但是还存在一种序列化/反序列化,那就是将对象序列化为二进制文件,将二进制文件反序列化为对象。下面我会对这三种序列化和反序列化进行解释。

1、Json

Json的英文全称是JavaScript Object Notation,是一种轻量级的数据交换格式,完全独立于语言的文本格式,易于人阅读和编写,同时也易于机器解析和生成。Json是目前互联网中主流的交换格式,同时也是很多开发语言配置文件的主流格式。

在.Net中存在两个类对Json进行处理,分别是DataContractJsonSerializer和JavaScriptSerializer,这两种类的功能基本一致。DataContractJsonSerializer位于命名空间 System.Runtime.Serialization.Json下,他的特点是必须用DatContract以及DataMember属性标记成员。JavaScriptSerializer位于命名空间System.Web.Script.Serialization下,通过名字和他所在的命名空间我们可以得知他主要用在网络通信中,他可以序列化任何类型的对象。同样.Net中也存在一个强大的第三方Json序列化/反序列化库 Newtonsoft.Json,他比前两个类用起来方便很多。下面我们对这三个序列化/反序列化的方式分别进行讲解。

(1)DataContractJsonSerializer

首先我们需要在项目引用DataContractJsonSerializer所在的命名空间,这里主要注意的是我们不仅要在项目中添加System.Runtime.Serialization还需要添加引用System.ServiceModel.Web。将这两个命名空间添加到命名空间后就可以在代码中进入DataContractJsonSerializer的命名空间了。

using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

引入命名空间后,我们开始编写序列化类

     [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; }
}

在上述代码中,我们看到类的头部添加了DataContract特性,以及在类的属性上也增加了DataMenber特性,一旦一个类被声明为DataCOntract时,就代表着该类可以被序列化,并且可以在服务端和客户端传输。只有声明为DataContract的类型的对象可以被传送,而且只有成员属性会被传送,成员方法不会被传送。默认情况下类中的所有成员属性都不会被序列化传输出去,如果需要将成员数据传输出去就需要在属性头部加入DataMember。

下面我们就利用DataContractJsonSerializer对对象进行序列化和反序列化,代码如下:

     class Program
{
static void Main()
{
#region 对象转Json字符串 var student = new Student
{
Name = "小魔王",
Age = ,
Sex = ,
Address = new Address
{
City = "SD",
Road = "JS"
}
}; //利用WriteObject方法序列化Json
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Student));
var stream = new MemoryStream();
serializer.WriteObject(stream, student);
var bytes = new byte[stream.Length];
stream.Position = ;
stream.Read(bytes, , (int)stream.Length);
var strJson = Encoding.UTF8.GetString(bytes);
Console.WriteLine(strJson); #endregion #region Json字符串转对象 stream = new MemoryStream(Encoding.UTF8.GetBytes(strJson));
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.Address.Road}"); #endregion Console.ReadKey();
}
} [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; }
}

结果:

(2)JavaScriptSerializer

我们利用前面定义的类,来看一下JavaScriptSerializer的使用方法,我们将前面定义的类中的DataContract和DataMember都去掉。我们如果要使用JavaScriptSerializer只需要引入System.Web.Script.Serialization命名空间即可。下面我们就利用JavaScriptSerializer对象进行序列化和反序列化,代码如下:

         static void Main()
{
#region 对象转Json字符串 var student = new Student
{
Name = "小魔王",
Age = ,
Sex = ,
Address = new Address
{
City = "SD",
Road = "JS"
}
}; //初始化
JavaScriptSerializer serializer = new JavaScriptSerializer();
var strJson = serializer.Serialize(student);
Console.WriteLine(strJson);
#endregion #region Json字符串转对象 student = serializer.Deserialize<Student>(strJson);
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.ReadKey();
}
} class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
} class Address
{
public string City { get; set; }
public string Road { get; set; }
}

结果:

(3)Newtonsoft.Json

NewtonSoft.Json功能有很多,除了序列化和反序列化之外,还有 Linq To Json、Json Path、XML support等,我们这篇文章之讲解其中的序列化和反序列化,使用NewtonSoft.Json前首先我们需要在nuget中搜索并安装,安装完成后引入NewtonSoft.Json,下面我么你来看一下具体使用:

     class Program
{
static void Main()
{
#region 对象转XML字符串 var student = new Student
{
Name = "小魔王",
Age = ,
Sex = ,
Address = new Address
{
City = "SD",
Road = "JS"
}
}; //初始化
var strJson = JsonConvert.SerializeObject(student);
Console.WriteLine(strJson);
#endregion #region Json字符串转对象 student = JsonConvert.DeserializeObject<Student>(strJson);
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.ReadKey();
}
} class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
} class Address
{
public string City { get; set; }
public string Road { get; set; }
}

结果:

从代码中我们可以看到 NewtonSoft.Json序列化和反序列化更加简单,简单到只需要一行代码就可以完成。

2、XML

在Json还没有出现之前,Xml是互联网上常用的数据交换格式和规范。.net中提供XmlSerializer类将对象序列化为XML和将XML反序列化为对象,使用方法是首先实例化,然后调用序列化/反序列化方法。下面我们依然使用最开始定义的那个类,来看看XmlSerializer的使用。使用前我们需要引入using System.Xml.Serialization命名空间。

具体序列化与反序列化方法如下:

     class Program
{
static void Main()
{
#region 对象转XML字符串 var student = new Student
{
Name = "小魔王",
Age = ,
Sex = ,
Address = new Address
{
City = "SD",
Road = "JS"
}
}; //初始化
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student));
using (var fs = new FileStream(@"F:\123.xml", FileMode.OpenOrCreate))
{
xmlSerializer.Serialize(fs, student);
}
Console.WriteLine("序列化完成");
#endregion #region Json字符串转对象 using (var fs = new FileStream(@"F:\123.xml", FileMode.OpenOrCreate))
{
//XmlReader xmlReader = new XmlTextReader(fs);
//student = xmlSerializer.Deserialize(xmlReader) as Student;
student = xmlSerializer.Deserialize(fs) 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.ReadKey();
}
} public class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
} public class Address
{
public string City { get; set; }
public string Road { get; set; }
}

结果:

 3、二进制

序列化为二进制,在实际开发中真有不少用到,但是我觉得还是有必要讲一讲,他的使用方法和XmlSerializer序列化/反序列化类似,首先实例化,然后调用序列化/反序列化方法。在进行序列化/反序列化前,首先引入命名空间System.Runtime.Serialization.Formatters.Binary,同时修改对象类如下:

     [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; }
}

上述代码中我们在类的头部加入了Serializable特性,这代表着整个类对象都需要序列化,如果我们不需要序列化其中的某个属性的话,只需要在该属性上加上NonSerialized特性即可,下面我们来看一下序列化/反序列化代码:

     class Program
{
static void Main()
{
#region 对象转XML字符串 var student = new Student
{
Name = "小魔王",
Age = ,
Sex = ,
Address = new Address
{
City = "SD",
Road = "JS"
}
}; BinaryFormatter binaryFormatter = new BinaryFormatter();
string fileName = Path.Combine(@"F:\", @"123.txt");
using (var stream = new FileStream(fileName, FileMode.OpenOrCreate))
{
binaryFormatter.Serialize(stream, student);
}
Console.WriteLine("序列化完成");
#endregion #region 字符串转对象 using (var fs = new FileStream(@"F:\123.txt", FileMode.OpenOrCreate))
{
student = binaryFormatter.Deserialize(fs) 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.ReadKey();
}
} [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; }
}

这篇文章详细的讲述了.Net中序列化与反序列化的相关知识和使用,序列化和反序列化的相关知识还有很多,这里所讲的都是开发中常用到的。好了,今天的知识就分享到这里了。

浅谈C#中的序列化与反序列化的更多相关文章

  1. 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变

    在net中json序列化与反序列化   准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...

  2. 浅谈jQuery中的Ajax

    浅谈jQuery中的Ajax 一.前言 jQuery 对 Ajax 操作进行了封装, 在 jQuery 中最底层的方法时 $.ajax(), 第二层是 load(), $.get() 和 $.post ...

  3. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  4. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  5. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  6. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  7. 转【】浅谈sql中的in与not in,exists与not exists的区别_

    浅谈sql中的in与not in,exists与not exists的区别   1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...

  8. 浅谈iOS中的userAgent

    浅谈iOS中的userAgent   User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...

  9. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

随机推荐

  1. [python]一些常用的python知识总结

    Pthon知识积累,遇到的各种python问题汇总 json.dumps()和json.loads()是json格式处理函数 json.dumps()函数是将一个Python数据类型列表进行json格 ...

  2. numpy.array 中的运算

    简单运算 现在有有个需求,给定一个数组,让数组中每一个数乘以2,怎么做呢 n = 10 L = [i for i in range(n)] L # [0, 1, 2, 3, 4, 5, 6, 7, 8 ...

  3. NOIP模拟27

    两个机房又和在一起考试 开场看了看T1,感觉挺水的,过. T2,这个式子有点奇怪,暂时没什么思路,过 T3,好像保留最后几位换个根处理一下就行了,过,先去打T1 于是T1大概打了0.5h,连暴力带正解 ...

  4. Unicode字符串和非Unicode字符串

    什么是Unicode? Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每 ...

  5. redis 底层数据结构

    简单动态字符串SDS 包含字符串长度,剩余可用长度,字符数组 用于Redis中所有的string存储 字典(map) 数组+链表形式,跟hashMap很像 链地址法解决hash冲突 rehash使用新 ...

  6. lqb 基础练习 特殊回文数

    基础练习 特殊回文数 时间限制:1.0s   内存限制:512.0MB     问题描述 123321是一个非常特殊的数,它从左边读和从右边读是一样的. 输入一个正整数n, 编程求所有这样的五位和六位 ...

  7. hdu 1863 畅通工程 (并查集 、 kruskal)

    畅通工程Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  8. .Net Core 使用NPOI导入数据

    一.搭建环境 1.新建ASP.NET Core Web 应用程序 2.选择API 3.引用Swashbuckle.AspNetCore NuGet 包进行安装. Swashbuckle.AspNetC ...

  9. spring security进阶 使用数据库中的账户和密码认证

    目录 spring security 使用数据库中的账户和密码认证 一.原理分析 二.代码实现 1.新建一个javaWeb工程 2.用户认证的实现 3.测试 三.总结 spring security ...

  10. 关于手机微信端ios的input不能选中问题解决方案

    最近在做一个微信端的商城,以前做web端的比较多,手机端做的相对来说要少点,老板说让我用俗称”靠谱的移动前端框架”—-AUI来搭建项目. 当时觉得用不用框架无所谓啦.结果后来写到一半把项目发布到手机上 ...