代码改变世界

Json和序列化总结

2017-08-03 20:23  小白admin  阅读(2527)  评论(0编辑  收藏  举报

一、序言

   遇到问题,就经常逛园,不知你是否曾有,曾经遇到的问题,或者在园子里看到问题的方案,过一段时间,有可能还会摔跤,哈哈...大神请勿喷,小弟记忆不太好,还过来找资料,如果自己写把问题或某个知识点总结,问题会更深刻,自己写的东西更能熟悉的了解。看别人写的文章,那是相当的羡慕,可能因为不敢写,懒惰等等个人原因,一直处于跑步机上停留,从没前进一大步,一直只是想写阶段。今天尝试改变一点点过去的自己,从部分知识的梳理总结,在梳理过程中如果出现不对,错误的地方,还请大神多多指出.......废话少说,第一天的主题:Json和序列化

二、json 和序列化

  首先我们先对json和序列化初步了解,之前面试面试官也问过相关的问题,什么是json,几种展现方式,你通常用序列化工具是什么,它有什么优势,下面通过简单的一个画图,说明json和序列化的认识和介绍:

三、代码实例

    我们很多时候会涉及到几个序列化对象的使用:DataContractJsonSerializer,JavaScriptSerializer 和 Json.NET(Newtonsoft)。 少废话,上代码,下面就一个个登场:

  第一个主角:JavaScriptSerializer

     (1)首先我们添加 先添加引用 System.Web.Extensions  

        备注:  JavaScriptSerializer类  应用json.net 使用序列化和反序列化,为启动Ajax的应用程序提供序列化和反序列化

         命名空间:   System.Web.Script.Serialization
         程序集:  System.Web.Extensions(位于 System.Web.Extensions.dll)

 

 代码 实例

 

 static void Main(string[] args)
        {
            List<User> userList = new List<User>() { 
            new User { Name="帅哥",Age=13,Gender=""},
            new User { Name="美女",Age=13,Gender=""}
            };
            // JavaScriptSerializer序列化 
            var javaScrittLizer = new JavaScriptSerializer().Serialize(userList);
            Console.WriteLine("序列化:"+javaScrittLizer);


            // JavaScriptSerializer反序列化
            string strJson = "{\"Name\":\"张三\",\"Age\":28,\"Gender\":\"女\"}";
            var deserialize = new JavaScriptSerializer().Deserialize<User>(strJson);
            Console.WriteLine("反序列化:姓名:"+ deserialize.Name+"年龄:"+deserialize.Age);
            Console.ReadKey();
        }

        public class User
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public string Gender { get; set; }
        }

 

结果:

 

 

第二个主角:Json.NET

     (1)第一步先在Negut添加安装包

   (2)添加2.添加Newtonsoft.Json  和  Newtonsoft.Json.Linq 引用

   (3)Newtonsoft.Json我们主要使用三个方法,基本就能满足我们日常开发: 序列化:SerializeObject(), 反序列化:DeserializeObject()

            还有一个可能没有对应的实体类型(或者说不想添加对应的实体类),这时候可以用匿名对象解析方法DeserializeAnonymousType(),方便快捷,对应代码如下:

    (4)总结:Newtonsoft.Json采用了Emit缓存优化,运行效率比较接近于fastCSharp生成的手工代码效率了,真的很不错,后面我们测试数据展示给你大家,

 // 1.先从NuGet中添加Json.net  
        // 2.添加Newtonsoft.Json  和  Newtonsoft.Json.Linq 引用
        static void Main(string[] args)
        {
            List<User> userList = new List<User>() { 
            new User { Name="帅哥",Age=13,Gender=""},
            new User { Name="美女",Age=13,Gender=""}
            };

            //序列化
            var userserializer = JsonConvert.SerializeObject(userList);
            Console.WriteLine("序列化:"+ userserializer);

            //反序列化
            string strJson = "{\"Name\":\"张三\",\"Age\":28,\"Gender\":\"女\"}";
            User user = JsonConvert.DeserializeObject<User>(strJson);
            Console.WriteLine("反序列化:姓名:{0},年龄:{1},性别:{2}", user.Name, user.Age, user.Gender);

            //匿名反序列化
            //可能没有对应的实体类型(或者说不想添加对应的实体类),这时候可以用匿名对象解析方法DeserializeAnonymousType(),方便快捷,对应代码如下:
            var tempEntity = new { Name = "0", Gender = string.Empty };
            tempEntity = JsonConvert.DeserializeAnonymousType("{\"Name\":\"帅哥\",\"Gender\":\"男\"}", tempEntity);
            Console.WriteLine("匿名序列化: 姓名:" + tempEntity.Name + ",性别:" + tempEntity.Gender);
            Console.ReadKey();
        }

        public class User
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public string Gender { get; set; }
        }

 效果显示:

  

 

 第三个主角:DataContractJsonSerializer

  (1)老规矩,需要添加引用:System.ServiceModel.Web 和 System.Runtime.Serialization

  (2)程序员就要干脆点,直接上代码:

       做DataContractJsonSerializer  demo测试的时候出现小插曲:

      (1)反序列化的时候,敲代码不小心  Deault 采用ANSI编码,不会编译报错,但是没有显示反序列化结果,大家小心,因为这里是UTF8  编码

      (2)User类中如果不加    [Serializable]   [DataContract]  这属性,会直接报错,为啥报错,我也百度了相关资料,代码中已经做出解释, 如果不加还会显示这样的字符串:<Name>k_BackingField

      大家可以去试试,为啥出现,代码和下面总结中会给出答案。

      还不懂的可以访问::: https://msdn.microsoft.com/zh-cn/library/bb412179.aspx

 /// <summary>
        /// DataContractJsonSerializer序列化案例
        /// 需要添加引用:System.ServiceModel.Web 和 System.Runtime.Serialization
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            List<User> userList = new List<User>() { 
            new User { Name="帅哥",Age=13,Gender=""},
            new User { Name="美女",Age=13,Gender=""}
            };

            //序列化
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<User>));
            using (MemoryStream stream = new MemoryStream())
            {
                serializer.WriteObject(stream, userList);
                var dataString = Encoding.UTF8.GetString(stream.ToArray());
                Console.WriteLine("序列化:" + dataString);
            }

            //序列化
            string strJson = "{\"Name\":\"张三\",\"Age\":28,\"Gender\":\"女\"}";
            DataContractJsonSerializer desserializer = new DataContractJsonSerializer(typeof(User));
            var mStream = new MemoryStream(Encoding.Default.GetBytes(strJson));
            User desUser = (User)desserializer.ReadObject(mStream);
            Console.WriteLine("反序列化:" + "姓名:" + desUser.Name + ",年龄:" + desUser.Age);
            Console.ReadKey();
        }

        //Serializable特性的作用
        ///序列化的attribute,是为了利用序列化的技术 准备用于序列化的对象必须设置 [System.Serializable] 标签,
        ///该标签指示一个类可以序列化。 便于在网络中传输和保存这个标签是类可以被序列化的特性,表示这个类可以被序列化。

        ///数据契约(DataContract) 服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型。
        ///一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送,如下所示。
        [Serializable]  //指示一个类可以序列化 
        [DataContract]
        public class User
        {
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public int Age { get; set; }
            [DataMember]
            public string Gender { get; set; }
        }

测试 效果:

 

上网也看了查了很多资料,他们三个比较中性能的比较:最好使用第三方:Json.net,(个人推荐

 资料链接:  http://json.codeplex.com/  也可以在里面下载源码,研究研究,嘿嘿

俗话说的好,不为书,只为实,那我们就来一下检测吧,实践才是检验真理的唯一标准,不能道听途说,哈哈哈哈。。。。。在此声明,我只能去验证它,不是挑战它,哈哈

 电脑配置配置原因,有些东西,没有显示上图效果,还是别的原因,大神有知道,还请多多指教  。。。。。

static void Main(string[] args)
        {
            User user = new User { Name = "帅哥", Age = 20, Gender = "" };
            List<User> userList = new List<User>();
            for (int i = 0; i < 5000; i++)
            {
                userList.Add(user);
            }

            Stopwatch sw = new Stopwatch();
            Stopwatch sw1 = new Stopwatch();
            Stopwatch sw2 = new Stopwatch();

            // JavaScriptSerializer序列化 
            sw.Start();
           //  var javaScrittLizer = new JavaScriptSerializer().Serialize(userList);
            Console.WriteLine("JavaScriptSerializer序列化:" + sw.Elapsed);

            //JsonConvert序列化
            sw1.Start();
            var userserializer = JsonConvert.SerializeObject(userList);
            Console.WriteLine("JsonConvert序列化:" + sw1.Elapsed);

            //DataContractJsonSerializer序列化
            sw2.Start();
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<User>));
            using (MemoryStream stream = new MemoryStream())
            {
                serializer.WriteObject(stream, userList);
                var dataString = Encoding.UTF8.GetString(stream.ToArray());
                Console.WriteLine("DataContractJsonSerializer序列化:" + sw2.Elapsed);
            }
            Console.ReadKey();
        }

        [Serializable]  //指示一个类可以序列化 
        [DataContract]
        public class User
        {
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public int Age { get; set; }
            [DataMember]
            public string Gender { get; set; }
        }

 

 

 

总结:

Newtonsoft.Json采用了Emit缓存优化,运行效率比较接近于fastCSharp生成的手工代码效率了,真的很不错
 DataContractJsonSerializer在.NET Framework 3.5中引入,主要因为WCF的引入而添加了这个对象序列化的基本方法,并且微软同时将JavaScriptSerializer打上了过时(obsolete)的标签,编译时就会有警告出现。
而在.NET Framework 3.5 SP1中,微软又将JavaScriptSerializer的“过时”标签给去掉了。
使用Reflector去比较这两个类的内部实现发现,DataContractJsonSerializer在对象序列化时进行了更为严格的检查,感兴趣的可以去System.Runtime.Serialization.Json下面的核心方法InternalWriteObjectContent去看其实现。
而在.NET Framework 3.5引入的自动属性,实际上就是个语法糖,编译器还是会生成一个int类型的<Name>k_BackingField的私有字段作为这个属性的后端字段,内部还是和以前的get/set方法一样。
所以直接使用DataContractJsonSerializer进行序列化时,又将编译器生成的k_BackingField带了出来。
而JavaScriptSerializer的实现则非常简单,将属性名和属性值分别存储在Dictionary里,然后进行字符串拼接返回而已,所以对类定义几乎没有检查并且对复杂类的支持不太好。

以上都是本人,个人理解,有错误的地方,还请大神多多指教.....哈哈哈,第一篇终于写完了,不好的地方多多包涵。