• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

兵棋研究所

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

开发随笔2-C++对象序列化和反序列化框架

在 开发随笔1 - 现代C++对象工厂模式实现 基础之上,我们可以开发一个基于模块工厂的序列化框架。这里采用boost中的property_tree来作为序列化输出和反序列化输入。

 

序列化基类定义如下

class Serializer
{
public:
    virtual ~Serializer() = default;
    virtual PTree serializeThisClass() = 0;
    virtual bool deserializeThisClass(const PTree &node) = 0;
    virtual const char* getClassName()const = 0;
 
    PTree serializeThisClassWithNodeName();
 
    bool saveToFile(const std::string &file);
    bool loadFromFile(const std::string &file);
};

实现如下

PTree Serializer::serializeThisClassWithNodeName()
{
    auto node = serializeThisClass();
    PTree doc;
    doc.add_child(getClassName(),node);
    return doc;
}
 
bool Serializer::saveToFile(const std::string &file)
{
    return savePTreeToFile(serializeThisClassWithNodeName(),file);
}
 
bool Serializer::loadFromFile(const std::string &file)
{
    PTree node;
    if(!readPTreeFromFile(file,node))
        return false;
 
    if(node.empty())
        return false;
 
    auto doc = node.get_child_optional(getClassName());
    if(!doc)
        return false;
    return deserializeThisClass(doc.value());
}

这是一个C++序列化接口类的设计,采用了面向对象的设计模式和模板方法模式。

并定义一系列基础序列化和反序列化函数

void deserialize(const PTree &node,sf::Vector2f& data);
void deserialize(const PTree &node,sf::Vector2i& data);
void deserialize(const PTree &node,sf::Vector2u& data);
void deserialize(const PTree &node,sf::Vector3f& data);
void deserialize(const PTree &node,sf::Vector3i& data);
void deserialize(const PTree &node,sf::IntRect& data);
void deserialize(const PTree &node,sf::FloatRect& data);
void deserialize(const PTree &node,sf::VideoMode& data);
 
PTree serialize(const sf::Vector2f& value);
PTree serialize(const sf::Vector2i& value);
PTree serialize(const sf::Vector2u& value);
PTree serialize(const sf::Vector3f& value);
PTree serialize(const sf::Vector3i& value);
PTree serialize(const sf::IntRect& value);
PTree serialize(const sf::FloatRect& value);

 以及一些辅助类宏定义

#define SERIALIZE_ENUM(node,Enum,value) node.add(#value,enumToString<Enum>(value));
#define SERIALIZE_ITEM(node,value) node.add(#value,value);
#define SERIALIZE_COLOR(node,value) node.add(#value,ColorConverter::toHexString(value));
#define SERIALIZE_NODE(node,value) node.add_child(#value,serialize(value));
#define SERIALIZE_POINTER(node,value) node.add_child(#value,value->serializeThisClassWithNodeName());
 
#define SERIALIZE_SUPER_NODE(node,SuperClass)\
    {\
        auto super = SuperClass::serializeThisClass();\
        node.add_child(#SuperClass,super);\
    }
 
#define DESERIALIZE_ENUM(node,Enum,value)\
    {\
        auto opt = node.get_optional<std::string>(#value);\
        if(opt)\
        {\
            value = stringToEnum<Enum>(*opt,Enum(0));\
        }\
    }
#define DESERIALIZE_ITEM(node,value)\
    {\
        auto opt = node.get_optional<decltype(value)>(#value);\
        if(opt)\
        {\
            value = *opt;\
        }\
    }
#define DESERIALIZE_COLOR(node,value)\
    {\
        auto opt = node.get_optional<std::string>(#value);\
        if(opt)\
        {\
            value = ColorConverter::fromHexString(*opt);\
        }\
    }
#define DESERIALIZE_NODE(node,data)\
    {\
        auto opt = node.get_child_optional(#data);\
        if(opt)\
        {\
            deserialize(opt.value(),data);\
        }\
    }
#define DESERILIZE_SUPER_NODE(node,SuperClass)\
    {\
        auto superName = SuperClass::getClassName();\
        auto opt = node.get_child_optional(superName);\
        if(opt)\
        {\
            SuperClass::deserializeThisClass(*opt);\
        }\
    }
 

对应的反序列化工厂定义如下

class DeserializerFactory : protected ObjectFactory<Serializer, std::string>
{
public:
    using BaseFactory = ObjectFactory<Serializer, std::string>;
    using SerializerPointer = std::shared_ptr<Serializer>;
 
    template<class Target>
    static std::shared_ptr<Target> deserializeFromFile(const std::string& file)
    {
        PTree node;
        if(!readPTreeFromFile(file,node))
        {
            LOG_ERROR("readPTreeFromFile {} failed",file);
            return nullptr;
        }
        return deserialize<Target>(node);
    }
 
    template<class Target>
    static std::shared_ptr<Target> deserialize(const std::string& name, const PTree& node)
    {
        auto option = node.get_child_optional(name);
        if (!option)
        {
            LOG_ERROR("deserialize {} failed",name);
            return nullptr;
        }
 
        auto value = option.value();
        if (value.empty())
            return nullptr;
 
        auto deserializer = BaseFactory::create(name);
        if (deserializer)
        {
            deserializer->deserializeThisClass(value);
            return std::dynamic_pointer_cast<Target>(deserializer);
        }
 
        LOG_ERROR("create object {} failed",name);
        return nullptr;
    }
 
    template<class Target>
    static std::shared_ptr<Target> deserialize(const PTree& node)
    {
        if(node.empty())
        {
            LOG_ERROR("PTree is empty.");
            return nullptr;
        }
 
        auto current = node.begin();
        auto deserializer = BaseFactory::create(current->first);
 
        if(deserializer)
        {
            deserializer->deserializeThisClass(current->second);
            return std::dynamic_pointer_cast<Target>(deserializer);
        }
 
        LOG_ERROR("create object {} failed",current->first);
        return nullptr;
    }
};
 

反序列化工厂继承于对象工厂,提供基于配置文件,指定节点,指定节点下节点名的对象反序列化功能。

使用例子如下

class Entity : public Serializer
{
public:
    PTree serializeThisClass()
    {
        PTree node;
        SERIALIZE_NODE(node,position)
        SERIALIZE_NODE(node,size)
        return node;
    }
    bool deserializeThisClass(const PTree &node)
    {
        DESERIALIZE_NODE(node,position)
        DESERIALIZE_NODE(node,size)
        return true;
    }
    const char *getClassName() const
    {
        return "Entity";
    }
 
    void print()
    {
        std::cout<<position.x<<","<<position.y<<","<<size.x<<","<<size.y<<std::endl;
    }
private:
    sf::Vector2f position;
    sf::Vector2f size;
};
 
REGISTER_PRODUCT(Serializer,Entity)
 
int main()
{
    PTree node;
    readPTreeFromFile("./e.xml",node);
    auto e = DeserializerFactory::deserialize<Entity>(node);
    if(e)
    {
        e->print();
    }
 
    return 0;
}
 

 

posted on 2025-11-13 16:54  ccsdu2004  阅读(5)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3