10-序列化

本篇博客对应视频讲解

回顾

在上一篇文章中,我们演示了如何使用异步实现多线程批量下载图片。 我们没有过多讲解线程Thread类,是因为在我们实际使用中,我们常用的需求,使用异步就能很好的解决,也不容易出错。 但我仍然建议大家阅读官方文档,以了解线程相关的内容。

序列化

我们知道,面向对象,我们把现实事物都抽象成对象,在编程语言中,使用类去定义它。但类或对象只是抽象的概念,我们在数据传递过程中,并不能直接传递这些抽象的东西。归根结底还是传递字节流。那么所谓序列化,其目的就是将对象转换为可传递数据的过程。 当然从数据转化为对象,自然就叫反序列化了。

关于序列化的概念及作用,务必阅读官方文档解释。

今天我们就了解一下,在序列化中最常使用的两种格式,XML与JSON。

XML

我们会演示一些最常用的操作,而关于更详尽的内容,我也整理给大家。

  1. 创建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非常相似,只是需要先定义数据协定,也就是在类与成员加上DataContractDataMember特性。

使用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,也可以使用序列化的方式对源数据进行转化或查询,最终得到我们要的内容。

也就是说,序列化是我们解析目标数据的一种方式,也可以说是常用的方式,但二者并不是一个概念。

posted @ 2018-10-11 17:32 MSDev_NilTor 阅读(...) 评论(...) 编辑 收藏