进阶系列(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,该方法会抛出错误。

posted @ 2017-04-27 18:27  StrugglingDave  阅读(1263)  评论(0编辑  收藏  举报