一、序言
遇到问题,就经常逛园,不知你是否曾有,曾经遇到的问题,或者在园子里看到问题的方案,过一段时间,有可能还会摔跤,哈哈...大神请勿喷,小弟记忆不太好,还过来找资料,如果自己写把问题或某个知识点总结,问题会更深刻,自己写的东西更能熟悉的了解。看别人写的文章,那是相当的羡慕,可能因为不敢写,懒惰等等个人原因,一直处于跑步机上停留,从没前进一大步,一直只是想写阶段。今天尝试改变一点点过去的自己,从部分知识的梳理总结,在梳理过程中如果出现不对,错误的地方,还请大神多多指出.......废话少说,第一天的主题: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里,然后进行字符串拼接返回而已,所以对类定义几乎没有检查并且对复杂类的支持不太好。
以上都是本人,个人理解,有错误的地方,还请大神多多指教.....哈哈哈,第一篇终于写完了,不好的地方多多包涵。