今天我利用这篇文章给大家讲解一下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. Numpy 中的聚合操作

    # 导包 import numpy as np sum np.random.seed(10) L = np.random.random(100) sum(L) np.sum(L) min np.min ...

  2. nginx篇高级之优化整理

    优化思路: 一.修改连接数和工作线程让其支持更多的并发量. worker_processes 2;                    //与CPU核心数量一致 worker_connections ...

  3. [考试反思]0819NOIP模拟测试26:荒芜

    这么正式的考试,明天应该就是最后一次了吧 然而..今天,我仍然没能抓住机会 RNBrank1:.skyh还是稳.外校gmk拿走第三. 四五六名都是63-64.第七50.第八39.我和三个并列的是第九. ...

  4. 理解PostgreSQL的模式、表、空间、用户间的关系

    在平时的工作中,我们经常接触到数据库表和用户以及角色的使用,由于经常使用默认的数据库表空间和模式(Schema),所以我们往往忽略了数据库表空间和模式的概念以及作用. 接下来,先介绍一下模式和表空间的 ...

  5. php pdo mysql存入转义

    php pdo mysql存入转义 因为存入html都是自动转义 相当于PHP的htmlspecialchars 所以读取的时候要加htmlspecialchars_decode

  6. 数据仓库ETL案例学习(一)

    来自课程案例学习   某跨国食品超市的信息管理系统,每天都会记录成千上万条各地连锁超市的销售数据.基于大数据的背景,该公司的管理层决定建立FoodMart数据仓库,期望能从庞大的数据中挖掘出有商业价值 ...

  7. SpringBoot 整合NoSql

    通用配置 maven依赖 添加Spring-Web和Spring-Security依赖,使用Spring-Security是因为使用SpringBoot的Redis依赖时,必须添加Spring-Sec ...

  8. Thinkphp5与QueryList,也可以实现采集(爬虫)页面功能

    QueryList 是什么 QueryList是一套用于内容采集的PHP工具,它使用更加现代化的开发思想,语法简洁.优雅,可扩展性强.相比传统的使用晦涩的正则表达式来做采集,QueryList使用了更 ...

  9. java编程思想第四版第十章总结

    1. 内部类的特性 他允许你把一些逻辑相关的类组织在一起. 2. 使用.this 如果你需要在内部类中堆外部类进行应用,可以使用外部类的名字后面加.this.下面展示了如何使用 .this packa ...

  10. nyoj 46-最少乘法次数 (递推)

    46-最少乘法次数 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:5 submit:18 题目描述: 给你一个非零整数,让你求这个数的n次方,每次相 ...