• 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; }
        }
    }

    运行结果截图:

    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在线安装示意图

    安装完毕后,会为我们的控制台项目默认添加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
        }
    }
  • 相关阅读:
    存储过程编译出现锁死情况的解决方法
    国庆带你回家
    端午假期·广州之旅
    造成开发效率底下并且代码难以维护的 35 个恶习
    Linux下mysql自动备份脚本
    在咸阳机场等候登机有感
    vant3图片二进制上传
    浅谈前端缓存(转至大佬)
    vue3中使用$nextTick
    调取接口分页
  • 原文地址:https://www.cnblogs.com/guwei4037/p/4334978.html
Copyright © 2020-2023  润新知