Generic Serializer——结构化数据的序列化

译者注:文中提到的Generic Serializer实现代码和demo程序在我上传的资源中:

代码:http://download.csdn.net/detail/manfred2manfred/5814883

demo:http://download.csdn.net/detail/manfred2manfred/5814895


By 11 Aug 2000


简介

MFC中的CObject和CArchive类提供了一些方法供framework进行序列化操作,但是这些方法无法对包含引用关系(cyclic references)的复杂数据结构进行序列化操作,或支持的效果很有限。

本文中所描述的GenericSerializeGenericDeserialize方法为上述的情况提供了一种通用的实现机制。这些泛型方法可以处理任何同构的结构化数据(datastructure consisting of nodes having all the same type)。

为使用上述方法,程序员需要自行实现一个叫做的Accessor类,并主要完成以下工作:

  • 将节点指针的类型定义(typedef)为Type;
  • 声明一个CArchive类型的成员变量 ar ;
  • 实现成员函数 Null(), 用来返回代表空(null)的 Type 值;
  • 实现序列化(serializing)和解序列化(deserializing)某个对象的函数;
  • 实现获取兄弟节点的函数。

接口类

template<class Access>
void GenericSerialize(const Access& a);

template<class Access>
void GenericDeserialize(const Access& a);

//The Access class must adhere to the following scheme
struct MyAccess
{
    typedef MyPointerType Type;
    CArchive ar;

    Type   Null()
           {/*your code*/}
    void   GetNeighbors(Type current,vector< pair<Type,int/*nTyp*/> >& vecNeighbors)
                    const
           { /*your code */ }//GetNeighbors(Null(),.. ) must place all root elements
                             // into <code>vecNeighbors</code>
    void   SerializeThis(Type owner,Type current,int nTyp)const	
           { /*your code/* }
    Type   DeserializeThis(Type owner,int nTyp)const
           { /*your code*/ }
    void   SetReference(Type owner,Type current,int nTyp)const
           { /*your code*/ }//current is an already deserialized reference of owner
};

Example A - 序列化 tree view 控件类

下列代码完成了对tree view空间的序列化工作:
void CGenericSerializeDemoView::TreeSerialize(CArchive& ar)
{
    TreeAccess access(m_Tree,ar); //user defined part of serialization

    if (ar.IsStoring())
    {	
        GenericSerialize(access);//general algorithm for serialization
    }
    else
    {	
        m_Tree.DeleteAllItems();
        GenericDeserialize(access); //general algorithm for deserialization
        ApplyItemStates(m_Tree.GetRootItem());
    }
}

Accessor类的实现:

struct TreeAccess{//user part for tree ctrl serialization

    TreeAccess(CTreeCtrl& rTree,CArchive& rAr):tree(rTree),ar(rAr){}

    typedef HTREEITEM   Type;   //'Type' is a mandatory member of any Access class

#define TA_eRoot       0
#define TA_eChild      1
#define TA_eSibling    2
    
    CTreeCtrl&  tree;   
    CArchive&   ar;     //'ar' is a mandatory member of any Access class

    HTREEITEM   Null()const    {return NULL;}
    void        GetNeighbors(HTREEITEM current,vector< pair<Type,int> >& vecNeighbors)
                    const
    {
        if(current==NULL){//get root items
            HTREEITEM   hItem= tree.GetRootItem();
            if(hItem){
                vecNeighbors.push_back( make_pair(hItem,TA_eRoot));
            }
        }else{
            HTREEITEM hItem= tree.GetNextSiblingItem(current);
            if(hItem){
                vecNeighbors.push_back(make_pair(hItem,TA_eSibling));
            }
            hItem= tree.GetChildItem(current);
            if(hItem){
                vecNeighbors.push_back(make_pair(hItem,TA_eChild));
            }
        }
    }
    void    SerializeThis(HTREEITEM owner,HTREEITEM current,int nTyp)const
    {
        ar  <<  tree.GetItemText(current);
        ar  <<  tree.GetItemState(current,TVIF_STATE);
    }
    HTREEITEM    DeserializeThis(HTREEITEM owner,int nTyp)const
    {
        CString strItemText;
        UINT   nState;
        ar  >> strItemText;
        ar  >> nState;

        HTREEITEM hItem;
        switch(nTyp){
        case TA_eRoot:     hItem= tree.InsertItem(strItemText);           break;
        case TA_eChild:    hItem= tree.InsertItem(strItemText,owner);     break;
        case TA_eSibling:  hItem= tree.InsertItem(strItemText,
                                    tree.GetParentItem(owner),owner);     break;
        }
        tree.SetItemData(hItem,nState);
        return hItem;
    }
    void    SetReference(HTREEITEM owner,HTREEITEM current,int nTyp)const
    {
    }
};

Example B - 序列化一个通用的关系图结构

下面的 Accessor类实现了对一个包含若干节点(node)的关系图结构的序列化,其中单个节点的定义如下:

struct Graph{ 
	Graph(int x=0,int y=0):x(x),y(y){} 
	int x,y; 
	vector<Graph*> vecConnections;
};
Accessor定义:
struct GraphAccess{//user part for graph serialization
    GraphAccess(vectorGraph& rGraph,CArchive& rAr):graph(rGraph),ar(rAr){}

    typedef Graph*   Type;      //'Type' is a mandatory member of any Access class

    vectorGraph&  graph;
    CArchive&       ar;         //'ar' is a mandatory member of any Access class

#define GA_eRoot    0
#define GA_eConnect 1

    
    Graph*  Null()const {return 0;}
    void    GetNeighbors(Graph* current,vector< pair<Type,int> >& vecNeighbors)const
    {
        if(current==NULL){//get root items
            for(unsigned i=0;i<graph.size();i++){
                vecNeighbors.push_back( make_pair(graph[i],GA_eRoot));
            }
        }else{
            for(unsigned i=0;i<current->vecConnections.size();i++){
                vecNeighbors.push_back( make_pair(graph[i],GA_eConnect));
            }
        }
    }
    void SerializeThis(Graph* owner,Graph* current,int nTyp)const
    {   
        ar  <<  current->x;
        ar  <<  current->y;
    }
    Graph* DeserializeThis(Graph* owner,int nTyp)const
    {   
        int x,y;
        ar  >>  x;
        ar  >>  y;
        graph.push_back(new Graph(x,y));
        return graph[graph.size()-1];
    }
    void SetReference(Graph* owner,Graph* current,int nTyp)const
    {
        if(owner!=0 && nTyp==GA_eConnect){
            owner->vecConnections.push_back(current);
        }
    }
};

关于作者

Martin Holzherr

Switzerland Switzerland

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django提供了多种序列化器来序列化多表数据,其中最常用的是ModelSerializer。 首先,你需要在你的serializers.py文件中导入ModelSerializer, models和serializers模块: ```python from django.db import models from rest_framework import serializers from .models import Model1, Model2 ``` 然后,你需要在serializers.py文件中定义你的ModelSerializer类,它将包含你要序列化的多个模型。例如,如果你要序列化Model1和Model2两个模型,可以按照以下方式编写一个ModelSerializer类: ```python class Model1Serializer(serializers.ModelSerializer): class Meta: model = Model1 fields = '__all__' class Model2Serializer(serializers.ModelSerializer): class Meta: model = Model2 fields = '__all__' ``` 现在,你可以使用这些序列化器来将多个模型序列化为JSON等格式。例如,如果你要将Model1和Model2两个模型的数据序列化为JSON格式,可以按照以下方式编写一个视图: ```python from rest_framework.generics import ListAPIView class ModelListAPIView(ListAPIView): queryset = Model1.objects.all() serializer_class = Model1Serializer ``` 在这个视图中,我们使用了Model1Serializer序列化Model1模型的数据。如果你想序列化Model2模型的数据,只需要将serializer_class属性设置为Model2Serializer即可。 同时,你也可以使用NestedSerializer来实现多表序列化。例如,如果你要序列化一个包含Model1和Model2的对象,可以按照以下方式编写一个NestedSerializer: ```python class Model2Serializer(serializers.ModelSerializer): class Meta: model = Model2 fields = '__all__' class Model1Serializer(serializers.ModelSerializer): model2 = Model2Serializer(many=True) class Meta: model = Model1 fields = '__all__' ``` 在这个NestedSerializer中,我们在Model1Serializer中定义了一个model2字段,并将其设置为Model2Serializer。这将允许我们序列化Model1和Model2两个模型的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值