[笔记]序列化与反序列化的讨论(二)

原创 2007年09月25日 14:34:00

上一篇中,讨论了序列化和反序列化的基础,同时简单说明了如何进行单个类的序列化和反序列化。

一般说来,使用默认的BinaryFormatter已经可得到很高效的字节流了。但是,实际应用中,由于部分数据可能无法被默认的模式自动序列化,自定义序列化就成为必不可少的一部分。自定义序列化的在进行XML序列化的时候尤其重要。因为XML序列化用的是浅序列化模式,也就是说,只有标记为public的公共属性会被序列化,而private的部分则不会被序列化到。通过自定义序列化,我们可以让XML序列化的时候,同时包含我们重建实例所需要的所有参数。dotNET是通过提供了ISerializable接口来达到实现自定义序列化的目的的。

namespace SimulationEnv
...{
    
class Program
    
...{
        
static void Main(string[] args)
        
...{
            BinaryFormatter formatter 
= new BinaryFormatter();
            Stream s 
= new MemoryStream();

            Player p 
= new Player("李逍遥");

            
// 序列化
            formatter.Serialize(s, p);

            
byte[] sav = ((MemoryStream)s).ToArray();
            Output(sav);
            Console.Write(
" ");
            Console.ReadLine();

            
// 反序列化
            s.Position = 0;
            Player psav 
= (Player)formatter.Deserialize(s);
            Console.WriteLine(psav.Name);
            Console.ReadLine();
        }


        
private static void Output(byte[] data)
        
...{
            
for (int i = 0; i < data.Length; i++)
            
...{
                
string str = data[i].ToString("X");
                
if (str.Length == 1)
                
...{
                    str 
= "0" + str;
                }

                Console.Write(str 
+ " ");
                
if ((i + 1% 16 == 0)
                
...{
                    Console.Write(
" ");
                }

            }

        }
    
    }


    [Serializable]
    
public class Player : ISerializable
    
...{
        
public string Name;

        
public Player(string Name)
        
...{
            
this.Name = Name;
        }


        
ISerializable Members#region ISerializable Members

        
// 该构造函数将在反序列化时候使用
        private Player(SerializationInfo info, StreamingContext context)
        
...{
            Name 
= info.GetString("Name");
        }


        
public void GetObjectData(SerializationInfo info, StreamingContext context)
        
...{
            info.AddValue(
"Name", Name);
        }


        
#endregion

    }


}

这里,构造函数Player(SerializationInfo info, StreamingContext context)被用来在反序列化时构造出和原实例完全一样的实例。由于这个构造函数的特殊性,为了防止别的程序有意无意的调用,该构造函数可以声明为private或者protected而不会影响系统本身对它的调用。也就是说,如果是一个已经封装的类,应该声明为private,未封装的类,应该声明为protected,来避免可能造成的系统安全隐患。

有趣的是,根据自定义序列化,我们可以序列化一个类以后,在反序列化的时候,将其反序列化为另外一个类。

namespace SimulationEnv
...{
    
class Program
    
...{
        
static void Main(string[] args)
        
...{
            BinaryFormatter formatter 
= new BinaryFormatter();
            Stream s 
= new MemoryStream();

            Player p 
= new Player("李逍遥");

            
// 序列化
            formatter.Serialize(s, p);

            
byte[] sav = ((MemoryStream)s).ToArray();
            Output(sav);
            Console.Write(
" ");
            Console.ReadLine();

            
// 反序列化
            s.Position = 0;
            TeamPlayer tp 
= (TeamPlayer)formatter.Deserialize(s);
            Console.WriteLine(tp.Name);
            Console.ReadLine();
        }


        
private static void Output(byte[] data)
        
...{
            
for (int i = 0; i < data.Length; i++)
            
...{
                
string str = data[i].ToString("X");
                
if (str.Length == 1)
                
...{
                    str 
= "0" + str;
                }

                Console.Write(str 
+ " ");
                
if ((i + 1% 16 == 0)
                
...{
                    Console.Write(
" ");
                }

            }

        }
    
    }


    [Serializable]
    
public class Player : ISerializable
    
...{
        
public string Name;

        
public Player(string Name)
        
...{
            
this.Name = Name;
        }


        
ISerializable Members#region ISerializable Members

        
// 该构造函数将在反序列化时候使用
        private Player(SerializationInfo info, StreamingContext context)
        
...{
            Name 
= info.GetString("Name");
        }


        
public void GetObjectData(SerializationInfo info, StreamingContext context)
        
...{
            info.AddValue(
"Name", Name);
            info.SetType(
typeof(TeamPlayer));
        }


        
#endregion

    }


    [Serializable]
    
public class TeamPlayer
    
...{
        
public string Name;
    }

}

通过info.SetType(),可以自定义在反序列化的时候,将其反序列化为某个特定的类。这点特性在某些时候很有用。比如,在进行系统整合的时候,服务端有一个类Product,且这个类是已经包装好的,不可以更改。但是客户端只能够发送Service的类。这时候,就可以用自定义的序列化,在序列化的时候,将Service类直接映射为Product类。这样,服务端进行反序列化的时候,得到的是Product类而不是Service。当然,这也需要服务端是使用反序列化来获得Product类的情况才可以。

反序列化作用

  • 2013年07月04日 07:12
  • 104KB
  • 下载

Gson使用心得(二):Map反序列化的一个陷阱

今天来讲java.util.Map的序列化和反序列化。 当中有一个陷阱,匪夷所思,请看代码。 import java.util.Date; import java.util.Hashtable; ...

Xml反序列化

  • 2013年09月15日 12:02
  • 25KB
  • 下载

Json.NET使用入门(二)【反序列化】

人生在世,一切都是机缘,顺其自然,内心就会逐渐清朗,生活,也是一首陪伴一生的乐曲。有时它激昂高亢,有时它曲折婉转,有时它忧郁沉闷。生活是快乐的,还是令人难以接受的,这取决于自己的心态。Deserial...
  • WuLex
  • WuLex
  • 2016年10月10日 11:13
  • 1082

JBOSS反序列化漏洞工具

  • 2016年03月28日 17:41
  • 5.31MB
  • 下载

java反序列化利用

  • 2017年08月31日 23:54
  • 33.79MB
  • 下载

修复weblogic的JAVA反序列化漏洞的多种方法

0x00 前言 目前oracle还没有在公开途径发布weblogic的JAVA反序列化漏洞的官方补丁,目前看到的修复方法无非两条: 使用SerialKiller替换进行序列化操作的Obje...

weblogic反序列化漏洞测试jar包

  • 2016年02月17日 16:49
  • 761KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[笔记]序列化与反序列化的讨论(二)
举报原因:
原因补充:

(最多只允许输入30个字)