进阶系列(3)—— 序列化与反序列化
一 、序列化与反序列化的介绍
序列化:将对象转换成字节流的过程,这样就可以轻松将对象保存在磁盘文件或数据库中。
反序列化:序列化的逆过程,就是将字节流转换回原来的对象的过程。
把对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为对象的过程称为对象的反序列化。两个环节为可逆性的。
二 、序列化的方法
先看一个例子,我们通过例子更加直观的对其进行了解。我们定义一个Person类,里面定义了一些字段,在Main方法中实例化一个对象。我们对person对象进行序列化与反序列化操作
public class Person { public string Name; public int Age; public Guid TokenId; public DateTime RegTime; public Person Child; public Person Friend; } class Program { static void Main(string[] args) { var person = new Person { Name = "张三<zhangsan>", Age = 12, TokenId = Guid.NewGuid(), Child = new Person { Age = 1, Name = "小张", RegTime = DateTime.Now, TokenId = Guid.NewGuid() } }; //序列化 JavaScriptSerializer serializer = new JavaScriptSerializer(); Console.WriteLine("使用 JavaScriptSerializer序列化"); var jsstr = serializer.Serialize(person); //使用 JavaScriptSerializer序列化 Console.WriteLine(jsstr); Console.WriteLine("使用 JsonConvert序列化"); string newtostr = JsonConvert.SerializeObject(person, Formatting.Indented, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });//使用 JsonConvert序列化 Console.WriteLine(newtostr); Console.ReadLine(); } }
(一)、JavaScriptSerializer序列化是先生成一个对象,然后调用它的成员函数Serialize进行序列化
注意添加对using System.Web.Script.Serialization的引用,使用此引用,需要首先引入System.Web.Extensions.dll文件。
JavaScriptSerializer serializer = new JavaScriptSerializer(); var jsstr = serializer.Serialize(person);
(二)、Json.net直接使用提供的静态成员JsonConvert.SerializeObject进行序列化
string newtostr = JsonConvert.SerializeObject(person);
上面红色框为JavaScriptSerializer的结果,下面绿色框为Json.net的结果,这里需要注意几个地方:
1、 JavaScriptSerializer序列化后的时间格式:"\/Date(1441813200214)\/" 表示的是1970年1月1日(DateTime的最小值)到date实际表示的日期之差的总毫秒数。通常我们需要把它转成标准的时间格式。可以用下面的方法进行字符串处理:
jsstr = Regex.Replace(jsstr, @"\\/Date\((\d+)\)\\/", match => { DateTime dt = new DateTime(1970, 1, 1); dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value)); dt = dt.ToLocalTime(); return dt.ToString("yyyy-MM-dd HH:mm:ss"); });
2、Json.net默认生成的日期也不方便客户端阅读,需要简单的处理一下:
string newtonstr = JsonConvert.SerializeObject(p, Formatting.Indented, new IsoDateTimeConverter() {DateTimeFormat = "yyyy-MM-dd HH:mm:ss"});
3、JavaScriptSerializer序列化会对特殊字符(如<>等)进行编码,比如上面的\u003c \u003e,很多人看到这个的时候,第一感觉就是太扯蛋了,接下来就是各种百度,怎么把这个转成正常的”<>”。实际上你不用做任何操作,这是标准的JS编码方式,前端会自行处理这个问题。比如:
<script type="text/javascript"> var str = 'yubaolee <yubaolee>' var str2 = 'yubaolee \u003cyubaolee\u003e'; alert(str == str2); //结果为true </script>
附:如果你真的不明白\u003c这到底是个什么玩意,请移步:字符编码。
三、 反序列化的方法
惯例依旧,我们先上一段代码,此部分代码是对上一段代码的再进行。
public class Person { public string Name; public int Age; public Guid TokenId; public DateTime RegTime; public Person Child; public Person Friend; } class Program { static void Main(string[] args) { var person = new Person { Name = "张三<zhangsan>", Age = 12, TokenId = Guid.NewGuid(), Child = new Person { Age = 1, Name = "小张", RegTime = DateTime.Now, TokenId = Guid.NewGuid() } }; ////序列化 //JavaScriptSerializer serializer = new JavaScriptSerializer(); //Console.WriteLine("使用 JavaScriptSerializer序列化"); //var jsstr = serializer.Serialize(person); //使用 JavaScriptSerializer序列化 //Console.WriteLine(jsstr); Console.WriteLine("使用 JsonConvert序列化"); string newtostr = JsonConvert.SerializeObject(person, Formatting.Indented, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });//使用 JsonConvert序列化
//反序列化 JavaScriptSerializer serializer = new JavaScriptSerializer(); var objOne = serializer.Deserialize<Person>(newtostr); var objTwo = JsonConvert.DeserializeObject<Person>(newtostr);
Console.WriteLine(newtostr); Console.ReadLine(); }
(一)、使用JavaScriptSerializer方法进行反序列化
JavaScriptSerializer serializer = new JavaScriptSerializer(); var objOne = serializer.Deserialize<Person>(newtostr);
(二)、使用JsonConvert方法进行反序列化
var objTwo = JsonConvert.DeserializeObject<Person>(newtostr);
四、 几种方式效率的对比
详细对比过程请参阅:https://github.com/kevin-montrose/Jil
五、 Json的定义
谈到序列化与反序列,我们不得不提到一种运用非常广泛的数据格式:Json。在用.net处理的时候,我们经常用的都是序列化与反序列化,就是我们上面讲解的知识点,接下来我们会接着继续讲解Json数据格式,在前端的处理形式。
JSON 的语法可以表示以下三种类型的值。
简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null。但 JSON 不支持 JavaScript 中的特殊值 undefined。
对象:对象作为一种复杂数据类型,表示的是一组无序的键值对儿。而每个键值对儿中的值可以是简单值,也可以是复杂数据类型的值。
数组:数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中的值。数组的值也可以是任意类型——简单值、对象或数组。Json不支持变量、函数或对象实例,它就是一种表示结构化数据的格式,虽然与 JavaScript 中表示数据的某些语法相同,但它并不局限于 JavaScript 的范畴。
六 、JSON对象
JSON对象有两个方法: stringify()和 parse()。在最简单的情况下,这两个方法分别用于把JavaScript 对象序列化为 JSON字符串和把 JSON字符串解析为原生 JavaScript 值。例如:
var book = { title: "Professional JavaScript", authors: [ "Nicholas C. Zakas" ], edition: 3, year: 2011 }; var jsonText = JSON.stringify(book);
这个例子使用 JSON.stringify()把一个 JavaScript 对象序列化为一个 JSON 字符串,然后将它保存在变量 jsonText 中。默认情况下, JSON.stringify()输出的 JSON 字符串不包含任何空格字符或缩进,因此保存在 jsonText 中的字符串如下所示:
{"title":"Professional JavaScript","authors":["Nicholas C. Zakas"],"edition":3, "year":2011}
将 JSON 字符串直接传递给 JSON.parse()就可以得到相应的 JavaScript 值。例如,使用下列代码就可以创建与 book 类似的对象:
var bookCopy = JSON.parse(jsonText);
注意,虽然 book 与 bookCopy 具有相同的属性,但它们是两个独立的、没有任何关系的对象。如果传给 JSON.parse()的字符串不是有效的 JSON,该方法会抛出错误。