10-序列化
本篇博客对应视频讲解
回顾
在上一篇文章中,我们演示了如何使用异步实现多线程批量下载图片。
我们没有过多讲解线程Thread
类,是因为在我们实际使用中,我们常用的需求,使用异步就能很好的解决,也不容易出错。
但我仍然建议大家阅读官方文档,以了解线程相关的内容。
序列化
我们知道,面向对象,我们把现实事物都抽象成对象,在编程语言中,使用类去定义它。但类或对象只是抽象的概念,我们在数据传递过程中,并不能直接传递这些抽象的东西。归根结底还是传递字节流。那么所谓序列化,其目的就是将对象转换为可传递数据的过程。 当然从数据转化为对象,自然就叫反序列化了。
关于序列化的概念及作用,务必阅读官方文档解释。
今天我们就了解一下,在序列化中最常使用的两种格式,XML与JSON。
XML
我们会演示一些最常用的操作,而关于更详尽的内容,我也整理给大家。
我们可以使用XElement 或XDocument去生成和操作XML。但通常情况下我们更关注如何将现在对象转换成XML,以及如何将XML转换成对象。 以下例子: 先定义Course与Blog类.
/// <summary> /// 课程类 /// </summary> public class Course { /// <summary> /// 课程名称 /// </summary> public string Name { get; set; } //[XmlElement(ElementName="Blog")] //[XmlArray("BlogList")] public Blog[] Blogs { get; set; } } /// <summary> /// 博文 /// </summary> public class Blog { /// <summary> /// 标题 /// </summary> public string Title { get; set; } /// <summary> /// 内容 /// </summary> //[XmlIgnore] public string Content { get; set; } /// <summary> /// 作者 /// </summary> [XmlAttribute(AttributeName = "author")] public string Author { get; set; } = "NilTor"; }
序列化与反序列化
// 创建对象 var course = new Course() { Name = "C#快速入门", Blogs = new Blog[] { new Blog { Title= "序列化", Content = "C#序列化内容" }, new Blog { Title="Linq", Content= "如何使用Linq" } } }; // 序列化,object->xml var ser = new XmlSerializer(typeof(Course)); var writer = new StringWriter(); ser.Serialize(writer, course); File.WriteAllText("course.xml", writer.ToString(), Encoding.Unicode); // 反序列化,xml->object var fileStream = new FileStream("course.xml", FileMode.Open); var course1 = ser.Deserialize(fileStream); Console.ReadLine();
JSON
json序列化应该说在Web开发中是再常见不过的了。在.Net中,我们可以使用DataContractJsonSerializer
类进行序列化与反序列化,使用方法与XmlSerializer非常相似,只是需要先定义数据协定,也就是在类与成员加上DataContract
或DataMember
特性。
使用DataContractJsonSerializer
参考官方的例子:
[DataContract] internal class Person { [DataMember] internal string name; [DataMember] internal int age; } Person p = new Person(); p.name = "John"; p.age = 42; // 序列化 MemoryStream stream1 = new MemoryStream(); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person)); ser.WriteObject(stream1, p); stream1.Position = 0; StreamReader sr = new StreamReader(stream1); Console.Write("JSON form of Person object: "); Console.WriteLine(sr.ReadToEnd()); // 反序列化 stream1.Position = 0; Person p2 = (Person)ser.ReadObject(stream1);
不难发现,无论是Json还是Xml,我们进行(反)序列化操作都是通过流(stream),所谓流,只是一种形象的表述,表示处于一种"流"的状态,里面的内容(一个个字节)并不代表任何含义。stream只是实现了一系列接口,这些接口能对字节进行相关的操作。有点类似String与StringBuilder。 说到底,无论是字符编码,还是序列化,我们都要先将内容"解析"到字节的层面,然后再进行相关的转化操作。
使用Newtonsoft.Json
这是一个第三方类库,但却是最流行,最常用的类库,其功能相当丰富,使用起来也更加方便实用。所以,通常我们需要进行Json的(反)序列化时,会建议使用该库类进行相关的操作。 以下是示例代码:
// 序列化,object->json var json = JsonConvert.SerializeObject(course); Console.WriteLine(json); // 反序列化,json->object var course2 = JsonConvert.DeserializeObject<Course>(json);
我们可以看到,使用起来要简洁的多,推荐大家使用。
解析
序列化和解析还不是一个概念。序列化更具体一些,作用上文我们也提到了。而解析的概念是对目标进行分析,了解其含义。举个简单的例子,我们有一个XML或JSON文件,里面有我们需要的数据,我们通过一些方式把我们想要的数据获取到,这个过程就可以称之为解析。我们可以使用正则,可以使用linq,也可以使用序列化的方式对源数据进行转化或查询,最终得到我们要的内容。
也就是说,序列化是我们解析目标数据的一种方式,也可以说是常用的方式,但二者并不是一个概念。