8 Star 43 Fork 16

xyz347 / xpack

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

xpack

English

  • 用于在C++结构体和json/xml/yaml/bson/mysql/sqlite之间互相转换
  • 只有头文件, 无需编译库文件,所以也没有Makefile。
  • 支持bson,依赖于libbson-1.0,需自行安装。未经充分测试,具体请参考README
  • 支持MySQL,依赖于libmysqlclient-dev,需自行安装。未经充分测试
  • 支持Sqlite,依赖于libsqlite3,需自行安装。未经充分测试
  • 支持yaml,依赖于yaml-cpp,需自行安装。未经充分测试
  • 具体可以参考example的例子

基本用法

  • 结构体后面用XPACK宏包含各个变量,XPACK内还需要一个字母,不同字母的意义请参考FLAG
  • 用xpack::json::encode把结构体转json
  • 用xpack::json::decode把json转结构体
#include <iostream>
#include "xpack/json.h" // Json包含这个头文件,xml则包含xpack/xml.h

using namespace std;

struct User {
    int id;
    string  name;
    XPACK(O(id, name)); // 添加宏定义XPACK在结构体定义结尾
};

int main(int argc, char *argv[]) {
    User u;
    string data = "{\"id\":12345, \"name\":\"xpack\"}";

    xpack::json::decode(data, u);          // json转结构体
    cout<<u.id<<';'<<u.name<<endl;

    string json = xpack::json::encode(u);  // 结构体转json
    cout<<json<<endl;

    return 0;
}

容器支持

目前支持下列容器(std)

  • vector
  • set
  • list
  • map<string, T>
  • map<integer, T> // 仅JSON,XML不支持
  • unordered_map<string, T> (需要C++11支持)
  • shared_ptr (需要C++11支持)

FLAG

宏XPACK里面,需要用字母将变量包含起来,比如XPACK(O(a,b)),XPACK可以包含多个字母,每个字母可以包含多个变量。目前支持的字母有:

  • X。格式是X(F(flag1, flag2...), member1, member2,...) F里面包含各种FLAG,目前支持的有:
    • 0 没有任何FLAG
    • OE omitempty,encode的时候,如果变量是0或者空字符串或者false,则不生成对应的key信息
    • EN empty as null, 用于json的encode,OE是直接不生成empty的字段,EN则是生成一个null
    • M mandatory,decode的时候,如果这个字段不存在,则抛出异常,用于一些id字段。
    • ATTR attribute,xml encode的时候,把值放到attribute里面。
    • SL single line, json encode的时候,对于数组,放在一行里面
  • C。格式是C(customcodec, F(flag1,flags...), member1, member2,...)用于自定义编解码函数,详情请参考自定义编解码
  • O。等价于X(F(0), ...) 没有任何FLAG。
  • M。等价于X(F(M),...) 表示这些字段是必须存在的。
  • A。别名,A(member1, alias1, member2, alias2...),用于变量和key名不一样的情况
  • AF。带FLAG的别名,AF(F(flag1, flag2,...), member1, alias1, member2, alias2...)
  • B。位域,B(F(flag1, flag2, ...), member1, member2, ...) 位域不支持别名
  • I。继承,I(baseclass1, baseclass2....),里面放父类
  • E。枚举:
    • 如果编译器支持C++11,不需要用E,枚举可以放X/O/M/A里面。
    • 否则枚举只能放E里面,不支持别名

别名

  • 用于变量名和key名不一致的场景
  • 格式是A(变量,别名....)或者AF(F(flags), 变量,别名....),别名的格式是"x t:n"的格式
    • x表示全局别名,t表示类型(目前支持json、xml、bson),n表示类型下的别名
    • 全局别名可以没有,比如json:_id是合法的
    • 类型别名可以没有,比如_id是合法的
    • 有类型别名优先用类型别名,否则用全局别名,都没有,则用变量名
#include <iostream>
#include "xpack/json.h"

using namespace std;

struct Test {
    long uid;
    string  name;
    XPACK(A(uid, "id"), O(name)); // "uid"的别名是"id"
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"id\":123, \"name\":\"Pony\"}";

    xpack::json::decode(json, t); 
    cout<<t.uid<<endl;
    return 0;
}

位域

  • 使用"B"来包含位域变量,位域不支持别名
#include <iostream>
#include "xpack/json.h"

using namespace std;

struct Test {
    short ver:8;
    short len:8;
    string  name;
    XPACK(B(F(0), ver, len), O(name)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"ver\":4, \"len\":20, \"name\":\"IPv4\"}";

    xpack::json::decode(json, t);
    cout<<t.ver<<endl;
    cout<<t.len<<endl;
    return 0;
}

继承

  • 使用"I"来包含父类。需要用到父类的变量就包含,用不到可以不包含。
  • 父类的父类也需要包含,比如class Base; class Base1:public Base; class Base2:public Base1;那么在Base2中需要I(Base1, Base)
  • 父类也需要定义XPACK/XPACK_OUT宏。
#include <iostream>
#include "xpack/json.h"

using namespace std;

struct P1 {
    string mail;
    XPACK(O(mail));
};

struct P2 {
    long version;
    XPACK(O(version));
};

struct Test:public P1, public P2 {
    long uid;
    string  name;
    XPACK(I(P1, P2), O(uid, name)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"mail\":\"pony@xpack.com\", \"version\":2019, \"id\":123, \"name\":\"Pony\"}";

    xpack::json::decode(json, t);
    cout<<t.mail<<endl;
    cout<<t.version<<endl;
    return 0;
}

枚举

  • 如果编译器支持C++11,则枚举和普通变量名一样,放X/O/M/A里面皆可。
  • 否则需要放到E里面,格式是E(F(...), member1, member2, ...)
#include <iostream>
#include "xpack/json.h"

using namespace std;

enum Enum {
    X = 0,
    Y = 1,
    Z = 2,
};

struct Test {
    string  name;
    Enum    e;
    XPACK(O(name), E(F(0), e)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"name\":\"IPv4\", \"e\":1}";

    xpack::json::decode(json, t);
    cout<<t.name<<endl;
    cout<<t.e<<endl;
    return 0;
}

自定义编解码

应用场景

  • 有些基础类型想用自定义方式编码,比如用字符串的方式来编码整数/浮点数
  • 部分类型可能不想按结构体变量逐个编码,比如定义了一个时间结构体:
struct Time {
    long ts; //unix timestamp
};

并不希望编码成{"ts":1218196800} 这种格式,而是希望编码成"2008-08-08 20:00:00"这种格式。

这里有两种方式:

  • 使用xtype,可以参考例子
  • 用C来包含需要自定义编解码的变量(下面简称C方法),可以参考例子

两种方法本质上都是自己去实现encode/decode,但是有以下区别:

  • xtype是类型级别的,也就是一旦某个类型用xtype封装之后,那么自定义的encode/decode就对这个类型生效。xtype无法作用于基本类型(int/string等)
  • C方法能支持基本类型(int/string等)和非基本类型,但是仅作用于用C包含的变量,比如int a;int b; O(a), C(custome_int, F(0), b);那么a还是用默认的编解码,b才是用自定义的编解码。
  1. xtype优先于XPACK宏,也就是定义了xtype的,会优先使用xtype的encode/decode
  2. C方法优先于xtype,也就是用C包含的变量,一定会用C里面指定的编解码方法。

用这两个特性,可以实现一些比较灵活的编解码控制,比如这个例子实现了一个根据变量情况来编码的功能,如果Sub.type==1则encode seq1,否则encode seq2. __x_pack_decode__x_pack_encode是XPACK宏给结构体添加的decode/encode函数,自定义编解码函数可以通过这些函数调用xpack默认的编解码功能。

union

可以使用自定义编解码来处理联合体,可以参考范例

数组

  • decode的时候如果元素个数超过数组的长度,会截断
  • char数组按有\0结束符处理
#include <iostream>
#include "xpack/json.h"

using namespace std;


struct Test {
    char  name[64];
    char  email[64];
    XPACK(O(name, email)); 
};

int main(int argc, char *argv[]) {
    Test t;
    string json="{\"name\":\"Pony\", \"email\":\"pony@xpack.com\"}";

    xpack::json::decode(json, t);
    cout<<t.name<<endl;
    cout<<t.email<<endl;
    return 0;
}

不定类型

  • 用于json的schema不确定的场景
  • xpack::JsonData来接收这些信息
  • 可以参考例子
  • xpack::JsonData主要的方法有:
    • Type。用于获取类型
    • IsXXX系列函数。用于判断是否是某种类型,基本等价于return Type()==xxxx;
    • GetXXX系列函数。用来提取值。
    • 重载bool。用来判断是否是一个合法的JsonData。
    • Size。用于数组类型判断元素的个数
    • operator [](size_t index) 用来取数组的第index个元素(从0开始)
    • operator [](const char *key) 用来根据key取Object类型的元素
    • Begin。用来遍历Object的元素,取第一个。
    • Next。配合Begin使用,获取下一个元素。
    • Key。配置Begin和Next使用,遍历的时候获取Key

第三方类和结构体

  • 用XPACK_OUT而非XPACK来包含变量
  • XPACK_OUT必须定义在全局命名空间
#include <sys/time.h>
#include <iostream>
#include "xpack/json.h"

using namespace std;

/*
struct timeval {
    time_t      tv_sec;
    suseconds_t tv_usec;
};
*/

// timeval is thirdparty struct
XPACK_OUT(timeval, O(tv_sec, tv_usec));

struct T {
    int  a;
    string b;
    timeval t;
    XPACK(O(a, b, t));
};


int main(int argc, char *argv[]) {
    T t;
    T r;
    t.a = 123;
    t.b = "xpack";
    t.t.tv_sec = 888;
    t.t.tv_usec = 999;
    string s = xpack::json::encode(t);
    cout<<s<<endl;
    xpack::json::decode(s, r);
    cout<<r.a<<','<<r.b<<','<<r.t.tv_sec<<','<<r.t.tv_usec<<endl;
    return 0;
}

格式化缩进

  • encode缺省生成的json/xml是没有缩进的,适合程序使用,如果让人读,可以进行缩进。
  • encode的最后两个参数控制
    • indentCount 表示缩进的字符数,<0表示不缩进,0则是换行但是不缩进
    • indentChar 表示缩进的字符,用空格或者制表符

XML数组

  • 数组默认会用变量名作为元素的标签,比如"ids":[1,2,3],对应的xml是:
<ids>
    <ids>1</ids>
    <ids>2</ids>
    <ids>3</ids>
</ids>
  • 可以用别名的方式来控制数组的元素的标签,比如A(ids,"xml:ids,vl@id"),vl后面跟着一个@xx,xx就是数组的标签,生成的结果就是:
<ids>
    <id>1</id>
    <id>2</id>
    <id>3</id>
</ids>
  • 如果希望数组直接展开,而不是在外面包一层,可以用别名加"sbs"的flag来实现,比如A(ids, "xml:ids,sbs"),注意,sbs标签仅能用于数组,其他地方使用可能会崩溃
<ids>1</ids>
<ids>2</ids>
<ids>3</ids>

CDATA

  • 对于CDATA类型,需要用"cdata"的flag来实现,比如A(data, "xml:data,cdata")
  • cdata只能用std::string来接收
  • 如果变量对应的xml不是CDATA结构,会按普通字符串来处理比如<data>hello</data>也可以解析成功

Qt支持

  • 修改config.h,开启XPACK_SUPPORT_QT这个宏(或者在编译选项开启)
  • 当前支持 QString/QMap/QList/QVector

MySQL

  • 目前仅支持decode,还不支持encode
  • 未经过完整测试,使用需要谨慎
  • 当前支持类型有:
    • string。简单测试。
    • 整型。简单测试。
    • 浮点型。未测试。
    • 用整型(比如time_t)接收TIME/DATETIME/TIMESTAMP。未测试。
    • 自定义类型转换,is_xpack_mysql_xtype,类似于xtype。未测试。
  • api有两个(xpack::mysql::) :
    • static void decode(MYSQL_RES *result, T &val)
      • 用来将MYSQL_RES转成结构体或者vector<>,如果是非vector,则只转换第一个row
    • static void decode(MYSQL_RES *result, const std::string&field, T &val)
      • 用来解析某个字段,用于只想获得某个字段内容的场景,比如select id from mytable where name = lilei,只想获得id信息。val支持vector

重要说明

  • 变量名尽量不要用__x_pack开头,不然可能会和库有冲突。
  • vc6不支持。
  • msvc没有做很多测试,只用2019做过简单测试。
  • json的序列化反序列化用的是rapidjson
  • xml的反序列化用的是rapidxml
  • xml的序列化是我自己写的,没有参考RFC,可能有和标准不一样的地方.
  • 有疑问可以加QQ群878041110
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

用于C++结构体和json/xml/bson/mysql的互相转换 展开 收起
C++ 等 5 种语言
Apache-2.0
取消

发行版 (1)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
C++
1
https://gitee.com/xyz347/xpack.git
git@gitee.com:xyz347/xpack.git
xyz347
xpack
xpack
master

搜索帮助