如何自定义序列化和反序列化

分析问题

  在其他很多编程语言(比如C++)中,实现序列化和反序列化的过程往往需要程序员手动地编写代码。而.NET中提供的Serializable特性却帮助程序员非常便捷地申明一个可序列化的类型。但是,便捷的同时往往意味着缺乏灵活性。很多时候,由于业务逻辑的要求,程序员往往需要主动地控制序列化和反序列化的过程,.NET提供了ISerializable接口来满足自定义序列化需求。

  为了实现自定义的序列化和反序列化,程序员需要实现ISerializable接口,并且提供一个特定的在反序列化中构造对象的方法。下面的代码展示了自定义序列化和反序列化的类型模型:

class MyObject : ISerializable
    {
        protected MyObject(SerializationInfo info, StreamingContext context)
        {
            //实现反序列化
        }

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            //实现序列化
        }
    }

  正如读者所看到的,特定地实现反序列化的构造方法可以不是公共的构造方法。事实上,该构造方法的可访问级别并不影响反序列化,程序员可以根据需求把它定义为private和protected,通常情况下由于安全的关系,该构造方法不会被申明为public,这也是.NET小组没有把反序列化设计成通过接口来实现的原因。GetObjectData和特殊构造方法都接受两个参数,SerializationInfo类型参数的作用类似于一个哈希表,通过键/值对来存储整个对象的内容,而StreamingContext类型参数则包含了流的当前状态,程序员可以根据此参数来判断是否需要序列化和反序列化类型对象。

  如果基类实现了ISerializable接口,则派生类型需要针对自己的成员实现反序列化构造方法,并且重写基类中的GetObjectData方法。以下代码给出了一个具体的实例。

using System;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace TestCustomize
{
    //首先编写一个需要被序列化和反序列化的类型,这里需要注意的是,该类型将被其他类型继承
    [Serializable]
    class MyObject : ISerializable
    {
        private int _MyInt;
        [NonSerialized]
        private string _MyString;

        public MyObject(int i, string s)
        {
            _MyInt = i;
            _MyString = s;
        }

        public override string ToString()
        {
            return new StringBuilder().AppendFormat("整数是:{0}\r\n字符串是:{1}\r\n",_MyInt.ToString(),_MyString).ToString();
        }

        //实现自定义的反序列化
        protected MyObject(SerializationInfo info, StreamingContext context)
        {
            //从SerializationInfo结构中读取内容
            _MyInt = info.GetInt32("MyObjectInt");
            _MyString = info.GetString("MyObjectString");
        }

        //实现自定义的序列化
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            //写入SerializationInfo结构
            info.AddValue("MyObjectInt", _MyInt);
            info.AddValue("MyObjectString", _MyString);
        }
    }

    //随后编写一个继承该类型的子类,并且添加一个私有的成员变量。子类必须负责序列化和反序列化自己添加的成员。
    [Serializable]
    class MyObjectSon : MyObject
    {
        private string _SonString;
        public MyObjectSon(int i, string s)
            : base(i, s)
        {
            _SonString = s;
        }

        public override string ToString()
        {
            return new StringBuilder().AppendFormat("{0}子类的字符串是:{1}\r\n",base.ToString(),_SonString).ToString();
        }

        //实现反序列化,只负责子类添加的成员
        protected MyObjectSon(SerializationInfo info, StreamingContext context):base(info,context)
        {
            _SonString = info.GetString("MyObjectSonString");
        }

        //实现序列化,只负责子类添加的成员
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("MyObjectSonString", _SonString);
        }
    }

    //最后编写入口方法,对这两个类型对象进行序列化和反序列化。

    class CustomizeSerialization
    {
        //main方法,测试自定义的序列化和反序列化
        static void Main()
        {
            MyObjectSon obj = new MyObjectSon(10, "我是字符串");
            Console.WriteLine("初始对象:{0}", obj);
            byte[] data = Serialize(obj);
            Console.WriteLine("经过序列化和反序列化后:");
            Console.WriteLine(DeSerialize(data));
            Console.Read();

        }

        //序列化对象
        static byte[] Serialize(MyObjectSon obj)
        {
            IFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms=new MemoryStream ())
            {
                formatter.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        //反序列化对象
        static MyObjectSon DeSerialize(byte[] bytes)
        {
            IFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms=new MemoryStream (bytes))
            {
                return formatter.Deserialize(ms) as MyObjectSon;
            }
        }

    }
}

  由于手动地控制了序列化和反序列化,实现了类型中所有成员的序列化,所有类型的对象经过序列化和反序列化后被完整地还原了,包括被申明了NonSerialized特性的成员。下面是代码的执行结果。

注意

  实现子类的序列化和反序列化方法需要调用基类的序列化和反序列化实现,否则对象将无法被成功地序列化或者反序列化。

答案

  通过实现ISerialization接口中的GetObjectData方法可以实现自定义的序列化,而通过添加带有SerializationInfo和StreamingContext参数的构造方法可以自定义反序列化的过程。

  

 

如何自定义序列化和反序列化

时间: 2024-11-03 09:17:07

如何自定义序列化和反序列化的相关文章

c# 通过json.net中的JsonConverter进行自定义序列化与反序列化

相信大家在工作中会经常遇见对json进行序列化与反序列化吧,但通常的序列化与反序列化中的json结构与c#中的类模型结构是相对应的,我们是否可以在序列化一个对象时候,让我们json的数据结构能按照自己的意愿,而不必与该对象的数据结构一样呢?,比如说,一个对象,只有一个名为"ID"的int类型的属性,值为1,如果序列化该对象,则能得到json:{"ID":1},但我现在希望得到的json的"ID"值是bool类型:{"ID":t

自定义序列化和反序列化的java实现

package j2se.IO; import java.io.*; /**  * Created by jingqing.zhou on 2015/6/12.  * ByteArrayOutputStream :可以捕获内存缓冲区的数据,转换成字节数组.  * DataInputStream&DataOutputStream关心如何将数据从高层次的形式转化成低层次的形式.  * FileInputStream&FileOutputStream关心如何操作存储单元以接受和产生数据.  */

Java对象序列化与反序列化

Java对象序列化与反序列化 对象序列化的目标是将对象保存在磁盘中或者在网络中进行传输.实现的机制是允许将对象转为与平台无关的二进制流. java中对象的序列化机制是将允许对象转为字节序列.这些字节序列可以使Java对象脱离程序存在,从而可以保存在磁盘上,也可以在网络间传输. 对象的序列化是将一个Java对象写入IO流:与此对应的,反序列化则是从IO流中恢复一个Java对象. 实现序列化 如果要将一个java对象序列化,那么对象的类需要是可序列化的.要让类可序列化,那么这个类需要实现如下两个接口

给Ajax一个漂亮的嫁衣——Ajax系列之五(下)之序列化和反序列化

给Ajax一个漂亮的嫁衣——Ajax系列之五(下)之序列化和反序列化 标签: ajaxdictionaryjsonobject服务器function 2012-07-25 18:41 2242人阅读 评论(6) 收藏 举报  分类: Ajax(6)  版权声明:本文为博主原创文章,未经博主允许不得转载. Ajax最强悍的功能莫过于服务器和客户端之间的异步交互,他们在交互的时候不是通过soap协议等,而是通过回调函数,以Json的格式传送数据. 由于Json格式的限制,在很多情况下,稍微复杂一些的

深度剖析PHP序列化和反序列化

序列化 序列化格式 在PHP中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构. 序列化函数原型如下: string serialize ( mixed $value ) 先看下面的例子: class CC { public $data; private $pass; public function __construct($data, $pass) { $this->data = $data; $this->pass = $pass; } } $number = 34;

SpringBoot序列化与反序列化

目录 基础知识 序列化 jackson序列化规则 双向注解 @JsonIgnoreProperties @JsonProperty,@JsonGetter,@JsonSetter @JsonUnwrapped @JsonAnyGetter,@JsonAnySetter @JsonSerialize,@JsonDeserialize @JsonView 序列化注解 @JsonFormat @JsonIgnore @JsonIgnoreType @JsonInclude @JsonAutoDetec

结合手机上网流量业务来说明Hadoop中的自定义数据类型(序列化、反序列化机制)

大家都知道,Hadoop中为Key的数据类型必须实现WritableComparable接口,而Value的数据类型只需要实现Writable接口即可:能做Key的一定可以做Value,能做Value的未必能做Key.但是具体应该怎么应用呢?--本篇文章将结合手机上网流量业务进行分析. 先介绍一下业务场景:统计每个用户的上行流量和,下行流量和,以及总流量和. 本次描述所用数据: 日志格式描述: 日志flowdata.txt中的具体数据: 接下来贴出详细代码,代码中含有详细注释,从代码中可以看出,

XML序列化与反序列化+自定义XML注解框架XmlUtils

背景 前面一篇总结了Serializable的序列化与反序列化,现在接着总结XML.主要内容:XML基本的序列化与反序列化方法.一些注意事项.以及自定义了一个XML注解框架(简洁代码,解放双手). XML的序列化与反序列化 先与Serializable进行简单的对比: Serializable存储的文件,打开后无法正常查看,安全性高.xml文件可通过文本编辑器查看与编辑,可读性高(浏览器会格式化xml文件,更方便查看),安全性低: Serializable文件通过了签名,只能在自己的程序中反序列

序列化与反序列化总结(Serializable和Parcelable)

序列化是指将对象的状态信息转换为可以存储或传输的形式的过程. 在Java中创建的对象,只要没有被回收就可以被复用,但是,创建的这些对象都是存在于JVM的堆内存中,JVM处于运行状态时候,这些对象可以复用, 但是一旦JVM停止,这些对象的状态也就丢失了. 在实际生活中,需要将对象持久化,需要的时候再重新读取出来,通过对象序列化,可以将对象的状态保存为字节数组,需要的时候再将字节数组反序列化为对象. 对象序列化可以很容易的在JVM中的活动对象和字节数组(流)之间转换,广泛用于RMI(远程方法调用)以