从node.js转到c++,特别怀念在js中使用json那种畅快感。在c++中也使用过了些库,但提供的接口使用方式,总不是习惯,很烦锁,接口函数太多,不直观。参考了很多库,如:rapidjson, cJson, CJsonObject, drleq-cppjson, json11等。数据结构受cJOSN启发很大,解析部分借鉴了json11,向他们致敬。最后因为数据存储需要不区分型别,又要能知道其型别,所以选择了C++17才支持的std::variant以及std::any,最终,C++版本定格在c++17,本库设计为单头文件,且不依赖c++标准库以外的任何库。
本人姓名拼音第一个字母z加上json,即得本项目名称zjson,没有其它任何意义。我将编写一系列以z开头的相关项目,命名是个很麻烦的事,因此采用了这种简单粗暴的方式。
简单的接口函数、简单的使用方法、灵活的数据结构、尽量支持链式操作。使用模板技术,得以完成最简设计,为Json对象子对象的方法只需一个 ———— addSubitem,该方法自动识别是值对象还是子Json对象。采用链表结构(向cJSON致敬)来存储Json对象,请看我下面的数据结构设计,表头与后面的结点,都用使用一致的结构,这使得在索引操作([])时,可以进行链式操作。
项目目前完成大部分主要功能,具体情况请看任务列表。可以新建Json对象,增加数据,按key(Object类型)或索引(Array类型)提取相应的值或子对象,生成json字符串,并且实现从json字符串构造Json对象。
已经做过内存泄漏测试,析构函数能正确运行,百万级别生成与销毁未见内存明显增长。
编写了大量的单元测试用例,同时支持windws、linux和mac主流操作系统。
任务列表:
(内部使用,数据类型只在Json类内部使用)
enum Type {
Error, //错误,查找无果,这是一个无效Json对象
False, //Json值类型 - false
True, //Json值类型 - true
Null, //Json值类型 - null
Number, //Json值类型 - 数字,库中以double类型存储
String, //Json值类型 - 字符串
Object, //Json类对象类型 - 这是Object嵌套,对象型中只有child需要关注
Array //Json类对象类型 - 这是Array嵌套,对象型中只有child需要关注
};
class Json {
Json* brother; //与cJSON中的next对应,值类型才有效,指向并列的数据,但有可能是值类型,也有可能是对象类型
Json* child; //孩子节点,对象类型才有效
Type type; //节点类型
std::variant <int, bool, double, string> data; //节点数据
string name; //节点的key
}
公开的对象类型,json只支持Object与Array两种对象,与内部类型对应(公开类型)。
enum class JsonType
{
Object = 6,
Array = 7
};
接口列表
简单使用示例
Json subObject{{"math", 99},{"str", "a string."}}; //initializer_list方式构造Json对象
//initializer_list方式构造Json对象, 并且可以嵌套
Json mulitListObj{{"fkey", false},{"strkey","ffffff"},{"num2", 9.98}, {"okey", subObject}};
Json subArray(JsonType::Array); //数组对象以initializer_list方式增加元素
subArray.add({12,13,14,15}); //快速生成 [12,13,14,15] array json
Json ajson(JsonType::Object); //新建Object对象,输入参数可以省略
std::string data = "kevin";
ajson.add("fail", false); //增加false值对象
ajson.add("name", data); //增加字符串值对象
ajson.add("school-en", "the 85th.");
ajson.add("age", 10); //增加number值对象,此处为整数
ajson.add("scores", 95.98); //增加number值对象,此处为浮点数,还支持long,long long
ajson.add("nullkey", nullptr); //增加null值对象,需要送入nullptr, NULL会被认为是整数0
Json sub; //新建Object对象
sub.add("math", 99);
ajson.addValueJson("subJson", sub); //为ajson增加子Json类型对象,完成嵌套需要
Json subArray(JsonType::Array); //新建Array对象,输入参数不可省略
subArray.add("I'm the first one."); //增加Array对象的字符串值子对象
subArray.add("two", 2); //增加Array对象的number值子对象,第一个参数会被忽略
Json sub2;
sub2.add("sb2", 222);
subArray.addValueJson("subObj", sub2); //为Array对象增加Object类子对象,完成嵌套需求
ajson.addValueJson("array", subArray); //为ajson增加Array对象,且这个Array对象本身就是一个嵌套结构
std::cout << "ajson's string is : " << ajson.toString() << std::endl; //输出ajson对象序列化后的字符串, 结果见下方
string name = ajson["name"].toString(); //提取key为name的字符串值,结果为:kevin
int oper = ajson["sb2"].toInt(); //提取嵌套深层结构中的key为sb2的整数值,结果为:222
Json operArr = ajson["array"]; //提取key为array的数组对象
string first = ajson["array"][0].toString(); //提取key为array的数组对象的序号为0的值,结果为:I'm the first one.
mulitListObj序列化后结果为:
{
"fkey": false,
"strkey": "ffffff",
"num2": 9.98,
"okey": {
"math": 99,
"str": "a string."
}
}
ajson序列化后结果为:
{
"fail": false,
"name": "kevin",
"school-en": "the 85th.",
"age": 10,
"scores": 95.98,
"nullkey": null,
"subJson": {
"math": 99
},
"array": [
"I'm the first one.",
2,
{
"sb2": 222
}
]
}
详情请参看demo.cpp或tests目录下的测试用例
https://gitee.com/zhoutk/zjson
或
https://github.com/zhoutk/zjson
该项目在vs2019, gcc7.5, clang12.0下均编译运行正常。
git clone https://github.com/zhoutk/zjson
cd zjson
cmake -Bbuild .
---windows
cd build && cmake --build .
---linux & mac
cd build && make
run zjson or ctest
会有一系列项目出炉,网络服务相关,敬请期待...
zorm (关系数据库的通用封装)
https://gitee.com/zhoutk/zorm
或
https://github.com/zhoutk/zorm
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型