浅谈C#中的序列化与反序列化
今天我利用这篇文章给大家讲解一下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#中的序列化与反序列化的更多相关文章
- 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变
在net中json序列化与反序列化 准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...
- 浅谈jQuery中的Ajax
浅谈jQuery中的Ajax 一.前言 jQuery 对 Ajax 操作进行了封装, 在 jQuery 中最底层的方法时 $.ajax(), 第二层是 load(), $.get() 和 $.post ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 浅谈Java中的equals和==
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...
- 转【】浅谈sql中的in与not in,exists与not exists的区别_
浅谈sql中的in与not in,exists与not exists的区别 1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...
- 浅谈iOS中的userAgent
浅谈iOS中的userAgent User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
随机推荐
- continue和break在while中用法
continue用法:结束本次循环,不执行continue下面的语句,返回执行下一次循环.注意:当执行完while的循环后,执行else 后的语句 break:结束循环,else下面语句也不执行
- 让NOI Linux变得可用
开始用NOI Linux-- 上古加阉割,还是32位,完全不可用的亚子-- 怎么办,我真的好想念16.04 于是就走上魔改之旅-- 一些神奇的操作 git 听说直接装的话会是上古版本 sudo add ...
- Mac中的Python安装selenium,结合chrom及chromdriver使用
一.安装selenium 1.在终端通过命令安装 pip3 install -U selenium 二.准备环境 1.在电脑中安装谷歌浏览器chrom,和下载估计浏览器驱动chromdriver,以下 ...
- Go 基础学习笔记(3)| 第一个程序 “helloworld”
//第一个程序总要说的清楚才行. //建议先运行起第一个程序实践后,再看后面的具体解答 一.helloworld 编写运行 1.编写源程序,在 ~ /hello/src 编写hello.g ...
- Machine Learning in Action ---- kNN
------------恢复内容开始------------ # -*- coding: utf-8 -*- """ Created on Thu Nov 14 19:2 ...
- China .NET Conf 2019-.NET技术架构下的混沌工程实践
这个月的8号.9号,个人很荣幸参加了China.NET Conf 2019 , 中国.NET开发者峰会,同时分享了技术专题<.NET技术架构下的混沌工程实践>,给广大的.NET开发小伙伴介 ...
- iOS--通过runtime完成归档,反归档
通过runtime,不管模型有多少属性,通过几句代码就能完成. 假设person类有N多个属性而是(这里随便写3个) .h #import <Foundation/Foundation.h> ...
- PHP---无限极分类数组处理
$array = array( 0=>array('id'=>1,'uid'=>0,'menuname'=>'菜单1','url'=>0,'addtime'=> ...
- 插入排序的代码实现(C语言)
void insert_sort(int arr[], int len) { for (int i = 1; i < len; ++i) { if (arr[i] < arr[i - 1] ...
- java编程思想第四版第八章习题
第一题 package net.mindview.polymorphism; //基类-自行车 class Cycle{ } //子类-单轮车 class Unicycle extends Cycle ...