在开发网络应用程序时,各个模块之间的数据通信可谓是家常便饭,为了应对这些数据通信时数据交换的要求,程序员发明了各种数据格式:采用二进制数据结构(早期 C 程序员)、采用 XML、采用SOAP(坑人的设计)、采用 URL 编码、采用JSON格式等。客户端与服务端交互时采用这些数据格式进行数据交换时,必然要经历数据编码及数据解码的繁琐过程。早期的二进制数据结构格式对于 C 程序员而是比较简单的,在解码时直接进行结构硬对齐就OK了,但对于其它语言(如 JAVA,PHP)则就麻烦很多,JAVA 语言不仅需要采用字节流一个一个对齐,而且还得要考虑到 C 结构体的数据打包填充方式;SOAP 方式看似满足了各类编程语言数据交换的目的,但数据臃肿是一个很大的问题,我们为了传输几个字节的数据则需要不得不封装大量的 XML 标记。为了使跨语言开发的程序员从麻烦的数据编解码中解脱出来,后来出来很多序列化/反序列化的工具库,比较著名的象 Facebook 的 thrift,Google 的 protobuf。这些工具库功能非常强大,但有一个问题是,这些工具库所要求的预先定义的 schema 的亲民性不够好,增加了额外的大量学习成本。

最近由 niukey@qq.com 为 acl 库新增了 C++ 对象序列化与反序列化库,大大提高了程序员的编程效率及代码准确率。acl 序列化库实现了 C++ struct 对象与 JSON 对象之间互转功能,使用方式非常简单。

一、acl 序列化库的功能特点

1、可以直接将 C++ struct 对象转换为 Json 对象,同时还可以将 Json 对象反序列化为 C++ struct 对象;

2、支持 C++ struct 对象中包含构造函数及析构函数;

3、C++ struct 对象中的成员支持常见基本类型(short, int, long, long long, char*)、标准 C++ 类对象;

4、C++ struct 对象中的成员支持指针类型;

5、C++ struct 对象中的成员支持常见 C++ 容器类型:std::vector、std::list、std::map,且支持容器对象的内部嵌套;

6、C++ struct 对象中的成员为基本数据类型(如:short, int, long, long long)和指针类型时,支持直接在 struct 中针对这些成员进行初始化(C++11);

7、支持在 C++ struct 中添加注释(// 或 /**/);

8、支持 C++ struct 对象的多继承;

9、支持在 C++ struct 对象中的多级包含,建议使用包含方式代替继承方式;

10、支持 C++ struct 成员增加注释项://Gson@optional 表示该成员变量为可选项,//Gson@required 表示该成员为必须项,默认为必须的。

二、使用 acl 序列化库的限制

1、struct 中的成员类型不能为 char 类型,主要是因为 Json 对象中不存在 char 类型;

2、struct 中的成员前不得有 const 常量限定词,主要是在反序列化时需要对这些成员进行赋值;

3、struct 中不支持 C++ 关键词:public、private、protected;

4、struct 中的成员变量名不得为:$json、$node、$obj,因为这些关键词被 acl 序列化库生成的代码占用;

5、存在包含关系的 struct 类型定义必须在同一个文件中;

6、不支持纯 C 语言的数组功能,比如,针对 int a[10],因无法确切知道数组 a 中真实存储的数量而无法进行序列化和反序列化,因此推荐使用 std::vector<int> 代替它。

三、使用 acl 序列化库的过程

1、首先编译 acl 库:在 acl 目录前运行:make build_one,会生成 acl 的三个基础库(lib_acl/lib/lib_acl.a, lib_protocol/lib/lib_protocol.a, lib_acl_cpp/liblib_acl_cpp.a),同时还会在 acl 根目录下生成这三个库的合集(lib_acl.a 和 lib_acl.so);

2、编译 acl 序列化工具:进入 app/gson 目录,运行 make,生成 gson 工具,该工具将被用于根据用户自定义 struct 生成序列化 C++ 代码;

3、定义自己的 struct 结构体(可以定义多个)并保存在文件中(文件后缀名为 .stub);

4、使用 gson 工具根据用户的 .stub 文件生成序列化所需的 C++ 代码:./gson -d path,其中 path 为保含 .stub 文件的目录,将会生成三个文件 gson.cpp、 gson.h 和 由 .stub 转换的 .h 头文件;

5、将 gson.h 和由 .stub 文件转换的 .h 头文件包含在自己的代码中;

6、针对用户自定义的每一个 struct,在 gson.h 头文件中均会提供 struct 对象的序列化和反序列化的方法,假设用户自定义了一个结构体类型:struct user,则在由工具 gson 生成的 gson.h 文件中包含如下五个方法:

1)、acl::string gson(const user &$obj);

将用户填充好的 user 对象 $obj 转换为 Json 字符串;

2)、acl::json_node& gson(acl::json &$json, const user &$obj);

将用户填充好的 user 对象 $obj 转化为 acl::json 对象 $json 中的一个 acl::json_node 节点对象并将之返回,这样用户可以将这个返回的 acl::json_node& 对象引用添加于 $json 对象中;

3)、acl::json_node& gson(acl::json &$json, const user *$obj);

功能与 2)中的方法相同,只是 $obj 参数为对象指针;

4)、std::pair<bool,std::string> gson(acl::json_node &$node, user &$obj);

将一个 acl::json_node Json 节点对象转化为用户自定义的 struct user 对象,如果 $node 为该 Json 对象中的根节点,则该根节点可由 $json.get_root() 获得,$obj 存储转换后的结果;

5)、std::pair<bool,std::string> gson(acl::json_node &$node, user *$obj);

功能与 5)中的方法相同,只是 $obj 参数为对象指针。

四、举例:

假设自定义结构对象如下:

Cpp代码
  1. // struct.stub
  2. #pragma once
  3. #include <string>
  4. struct user
  5. {
  6. std::string name;
  7. std::string domain;
  8. int age;
  9. bool male;
  10. };

应用操作 user 对象的过程如下:

Cpp代码
  1. // main.cpp
  2. #include "stdafx.h"
  3. #include <list>
  4. #include <vector>
  5. #include <map>
  6. #include <stdio.h>
  7. #include <iostream>
  8. #include <time.h>
  9. #include "struct.h"  // 由 gson 工具根据 struct.stub 转换而成
  10. #include "gson.h"   // 由 gson 工具根据 struct.stub 生成
  11. // 序列化过程
  12. static void serialize(void)
  13. {
  14. user u;
  15. u.name = "zsxxsz";
  16. u.domain = "263.net";
  17. u.age = 11;
  18. u.male = true;
  19. acl::json json;
  20. // 将 user 对象转换为 json 对象
  21. acl::json_node& node = acl::gson(json, u);
  22. printf("serialize:\r\n");
  23. printf("json: %s\r\n", node.to_string().c_str());
  24. printf("\r\n");
  25. }
  26. // 反序列化过程
  27. static void deserialize(void)
  28. {
  29. const char *s = "{\"name\": \"zsxxsz\", \"domain\": \"263.net\", \"age\": 11, \"male\": true}";
  30. printf("deserialize:\r\n");
  31. acl::json json;
  32. json.update(s);
  33. user u;
  34. // 将 json 对象转换为 user 对象
  35. std::pair<bool, std::string> ret = acl::gson(json.get_root(), u);
  36. // 如果转换失败,则打印转换失败原因
  37. if (ret.first == false)
  38. printf("error: %s\r\n", ret.second.c_str());
  39. else
  40. printf("name: %s, domain: %s, age: %d, male: %s\r\n",
  41. u.name.c_str(), u.domain.c_str(), u.age,
  42. u.male ? "yes" : "no");
  43. }
  44. int main(void)
  45. {
  46. serialize();
  47. deserialize();
  48. return 0;
  49. }

五、参考:

acl github:https://github.com/acl-dev/acl

acl osc:https://git.oschina.net/acl-dev/acl/tree/master

更多 C++ 序列化的例子:https://github.com/zhengshuxin/acl/tree/master/app/gson/test

acl 编译与使用:http://zsxxsz.iteye.com/blog/1506554

MFC开发IM-第二十四篇、使用 acl 库针对 C++ 对象进行序列化及反序列编程相关推荐

  1. MFC开发IM-第二十八篇、acl 的编译与使用

    转载来自::: http://zsxxsz.iteye.com/blog/1506554 ------------------------------------------- acl 库的功能参见文 ...

  2. python dataframe 新列_Python第二十四课:Pandas库(四)

    Python第二十四课:Pandas库(四)点击上方"蓝字",关注我们. 不知不觉,我们已经跨越了千难万险,从零开始,一步步揭开了Python神秘的面纱.学到至今,回过头,才晓得自 ...

  3. Python之路【第二十四篇】Python算法排序一

    什么是算法 1.什么是算法 算法(algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出.简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果. ...

  4. 第二十四篇:可靠信号机制

    前言 曾经的 UNIX 系统中,信号的不可靠的.什么是不可靠?就是信号丢失呗.那什么是信号丢失?就是当系统正在处理某个事务的时候,如果收到了某个信号,但它不能及时处理这个信号,那么只能忽略掉此信号. ...

  5. SpringBoot第二十四篇: springboot整合docker

    这篇文篇介绍,怎么为 springboot程序构建一个docker镜像.docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的 ...

  6. setitimer 创建两个定时器_JavaScript第二十四篇 高级定时器(下)

    数组分块 所谓数组分块,就是当你发现某个循环占用了大量时间,同时对于上述两个问题,你的回答都是"否",那么你就可以使用定时器分割这个循环. 思路是结合定时器进行递归调用定时器 基本 ...

  7. “约见”面试官系列之常见面试题第二十四篇之vue-router使用(建议收藏)

    开发的时候有时候会遇到一种情况,比如 :点击这个链接跳转到其他组件的情况,通常会跳转到新的页面,蛋是,我们不想跳转到新页面,只在当前页面切换着显示,那么就要涉及到路由的嵌套了,也可以说是子路由的使用. ...

  8. MFC开发IM-第二十六篇、vs2008添加库文件

    [Setting]VS2008项目怎样添加"依赖(lib)"."库目录(Libs)"."包含目录(include)"和"引用动态链 ...

  9. 【Java成王之路】EE初阶第二十四篇: Servlet

    Sevlet Servlet 是什么 Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一 个 web app. Tomcat 是一个 ...

最新文章

  1. Office 365管理员指引 17——Sharepoint 讨论版
  2. MacOS使用Charles抓去HTTPS数据
  3. 高基数特征的预处理方式
  4. python2异步编程_python异步编程入门
  5. python list常用方法_Python中列表(List)的基本用法
  6. 数据库笔记2:SQL运算符
  7. 【转】Postman系列二:Postman中get接口实战讲解(接口测试介绍,接口测试流程,头域操作)
  8. 博弈——NimSG函数函数(hdu1848)
  9. file_get_contents(php://input)
  10. ubuntu20.04 cudnn7.5.6_每日一题|小学数学1——6年级天天练习
  11. java面试宝典pdf下载_Java面试问答PDF电子书免费下载(250+问题,60页)
  12. 【VB.Net】泛型IIF
  13. Android软键盘问题
  14. CuteFTP下载大文件时报错
  15. 8cm等于多少像素_像素和厘米的换算
  16. 金山词霸不断的弹出窗口(金山词霸防欺诈提示),犹如病毒软件
  17. 线性地址转换物理地址
  18. edge 临时文件夹 位置_如何更改Microsoft Edge的下载文件夹的位置
  19. 11月13日科技资讯|天猫回应“双11数据造假”:已启动司法流程;小米折叠手机专利曝光;ASP.NET感染勒索软件|极客头条
  20. Python 教程视频汇总

热门文章

  1. [Winform] DataGridView辅助类
  2. NOI2016区间bzoj4653(线段树,尺取法,区间离散化)
  3. Spring+SpringMVC+MyBatis深入学习及搭建(九)——MyBatis和Spring整合
  4. 使用Ant 和 Maven打包发布命令行程序(转载)
  5. 浏览器调试时控制台出现:Uncaught SyntaxError: Unexpected identifier
  6. Python3 下找不到urllib2的问题
  7. 在Oracle用SQL处理以 System.currentTimeMillis
  8. 微服务的一种开源实现方式——dubbo+zookeeper
  9. 解决main No MyBatis mapper was found in 的警告
  10. fast.ai 深度学习笔记:第一部分第二课