C# 序列化、反序列化

C# 序列化、反序列化

刚刚碰巧群里有人问这个问题,而之前的博客中并没有提及,打算弄一篇博客简单提及一下这个知识点。

MSDN文档中提及了序列化、反序列化的概念,这里引用一下。

序列化:将对象状态转换为可保持或传输的形式的过程。

反序列化:是序列化的逆过程,就是将流转换为对象的过程。

这两个过程一起保证数据易于传输和存储。

详细的请参考:http://msdn.microsoft.com/zh-cn/library/7ay27kt9(v=vs.100).aspx

下面直接给出完整的代码,该代码演示了如何序列化一个对象以及反序列化(还原对象)的过程。

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Object student = new Student() { StudentID = "007", StudentName = "guwei4037" };

            string result = ObjectToString<Object>(student);
            Console.WriteLine(result + "
");

            Student newResult = StringToObject<Student>(result);
            Console.WriteLine("ID:{0}, Name:{1}", newResult.StudentID, newResult.StudentName);
        }

        /// <summary>
        /// 对象转字符串(序列化后转Base64编码字符串)
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>字符串</returns>
        public static string ObjectToString<T>(T obj)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
                stream.Position = 0;
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, buffer.Length);
                return Convert.ToBase64String(buffer);
            }
        }

        /// <summary>
        /// 字符串转对象(Base64编码字符串反序列化为对象)
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>对象</returns>
        public static T StringToObject<T>(string str)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                byte[] bytes = Convert.FromBase64String(str);
                stream.Write(bytes, 0, bytes.Length);
                stream.Position = 0;
                IFormatter formatter = new BinaryFormatter();
                return (T)formatter.Deserialize(stream);
            }
        }
    }

    /// <summary>
    /// 可序列化的类,用Serializable标示此类可序列化
    /// </summary>
    [Serializable]
    public class Student
    {
        public string StudentID { get; set; }
        public string StudentName { get; set; }
    }
}

运行结果截图:

C# 序列化、反序列化

XML序列化

示例:用XmlSerializer序列化一个学生对象。

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };

            using (FileStream stream = new FileStream("张三.xml", FileMode.OpenOrCreate))
            {
                XmlSerializer s = new XmlSerializer(typeof(Student));
                s.Serialize(stream, zhang3);
            }

            Console.WriteLine("对象序列化成功...");
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

如果程序没有发生异常,则可以在控制台项目binDebug目录下查看生成的张三.xml文件内容。

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>张三</Name>
  <Sex>Male</Sex>
  <Phone>13012345678</Phone>
  <Address>中国</Address>
</Student>

XML反序列化

示例:将上个例子中生成的张三.xml文件反序列化为C#中的张三对象。

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlSerializer d = new XmlSerializer(typeof(Student));
            using (FileStream stream = new FileStream("张三.xml", FileMode.OpenOrCreate))
            {
                object obj = d.Deserialize(stream);
                if (obj is Student)
                {
                    Student zhang3 = obj as Student;
                    Console.WriteLine("姓名:{0}
性别:{1}
电话:{2}
地址:{3}", zhang3.Name, zhang3.Sex, zhang3.Phone, zhang3.Address);
                }
            }
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

JSON序列化

Ø  JavaScriptSerializer

使用JavaScriptSerializer需要在项目中添加引用System.Web.Extensions,然后引用命名空间System.Web.Script.Serialization。

示例:使用JavaScriptSerializer将张三对象序列化为JSON字符串

using System.Web.Script.Serialization;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };
            JavaScriptSerializer j = new JavaScriptSerializer();
            string zhang3Json = j.Serialize(zhang3);
            Console.WriteLine(zhang3Json);
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

Ø  DataContractJsonSerializer

使用DataContractJsonSerializer需要在项目中添加引用System.Runtime.Serialization,然后引用命名空间System.Runtime.Serialization.Json。

示例:使用DataContractJsonSerializer将张三对象序列化为JSON字符串

using System.Runtime.Serialization.Json;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };
            DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(Student));
            using (FileStream fs = new FileStream("张三.json", FileMode.OpenOrCreate))
            {
                s.WriteObject(fs, zhang3);
            }
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

序列化完成后,可以在项目的bin/Debug目录下看到生成的张三.json文件。用notepad++等文本编辑器打开可以看到生成的json内容。

张三.json文件内容:

{"Address":"中国","Name":"张三","Phone":"13012345678","Sex":1}

Ø  Json.NET

示例:使用Json.NET需要添加引用Newtonsoft.Json,可以通过nuget在线安装或者直接下载Newtonsoft.Json开发包添加引用。

通过nuget在线安装示意图

C# 序列化、反序列化

安装完毕后,会为我们的控制台项目默认添加Newtonsoft.Json引用。

示例:使用Json.NET序列化张三对象为Json字符串

using Newtonsoft.Json;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };
//序列化
            string zhang3Json = JsonConvert.SerializeObject(zhang3); 

//输出结果:{"Name":"张三","Sex":1,"Phone":"13012345678","Address":"中国"}
            Console.WriteLine(zhang3Json);
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

可以看到输出结果中,Sex的值为1,并不是之前的Male。这是由于Json.NET在处理枚举时会默认将枚举元素的值输出。可以通过给枚举添加属性声明的方式输出枚举元素的名称。

将Student类修改如下:

public class Student
{
    public string Name { get; set; }
    [JsonConverter(typeof(StringEnumConverter))]
    public Sex Sex { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
}

引用StringEnumConverter类需要添加Newtonsoft.Json.Converters命名空间。通过如上的修改输出序列化JSON字符串时会得到枚举的名称。

JSON反序列化

Ø  JavaScriptSerializer

示例:使用JavaScriptSerializer将张三序列化生成的JSON字符串反序列化为张三对象

using System.Web.Script.Serialization;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };
            JavaScriptSerializer j = new JavaScriptSerializer();
            //序列化zhang3对象
            string zhang3Json = j.Serialize(zhang3);
            //反序列化zhang3对象
            Student zhang3FromJson = j.Deserialize<Student>(zhang3Json);
            Console.WriteLine("姓名:{0}
性别:{1}
电话:{2}
地址:{3}", zhang3FromJson.Name, zhang3FromJson.Sex, zhang3FromJson.Phone, zhang3FromJson.Address);
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

Ø  DataContractJsonSerializer

示例:使用DataContractJsonSerializer将张三.json文件反序列化为张三对象。

using System.Runtime.Serialization.Json;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(Student));
            using (FileStream fs = new FileStream("张三.json", FileMode.OpenOrCreate))
            {
                object obj = s.ReadObject(fs);
                if (obj is Student)
                {
                    Student zhang3FromJson = obj as Student;
                    Console.WriteLine("姓名:{0}
性别:{1}
电话:{2}
地址:{3}", zhang3FromJson.Name, zhang3FromJson.Sex, zhang3FromJson.Phone, zhang3FromJson.Address);
                }
            }
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}

Ø  Json.NET

示例:将张三的JSON字符串反序列化为张三对象

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
                Student zhang3 = new Student() { Name = "张三", Sex = Sex.Male, Phone = "13012345678", Address = "中国" };
                //序列化
                string zhang3Json = JsonConvert.SerializeObject(zhang3);
                //反序列化
                Student zhang3FromJson = JsonConvert.DeserializeObject<Student>(zhang3Json);
                Console.WriteLine("姓名:{0}
性别:{1}
电话:{2}
地址:{3}", zhang3FromJson.Name, zhang3FromJson.Sex, zhang3FromJson.Phone, zhang3FromJson.Address);
        }
    }

    public class Student
    {
        public string Name { get; set; }

        [JsonConverter(typeof(StringEnumConverter))]
        public Sex Sex { get; set; }
        public string Phone { get; set; }
        public string Address { get; set; }
    }

    public enum Sex
    {
        Female,
        Male
    }
}