jsoncpp与rapidjson易用性与性能评测

文章目录
jsoncpp与rapidjson易用性与性能评测
1. 概述
2. 易用性
2.1 jsoncpp
2.2 rapidjson
3. 性能
4.总结
jsoncpp与rapidjson易用性与性能评测
1. 概述
jsoncpp和rapidjson是两款常用C++11编写的第三方开源JSON序列化与反序列化库, 两者都基于MIT协议发布,对商用较友好,以下从使用上和性能上对两者做出评价,方便不同应用场景选择。

2. 易用性
2.1 jsoncpp
头文件源文件并存: 一般根据平台编译成动态库引入项目;
中间对象JSON value:构造较容易,使用较方便。
2.2 rapidjson
纯头文件: rapidjson只包含头文件,不包含源文件,非常方便集成到项目中;
中间对象JSON value: 构造较复杂, 涉及到内存分配器;
自包含:rapidjson完全是一个独立的项目,不依赖与第三个库,比如不依赖BOOST,甚至可以不依赖STL;
速度快:性能类似于strlen()。
在使用上jsoncpp更胜一筹,性能上rapidjson更好(见3.性能):
jsoncpp中,根节点和子节点都是用Json::Value, 且很方便使用[]操作符操作子节点,节点不存在则新建,存在则引用,而rapidjson只能在节点存在的情况下才能使用[], 否则断言失败,简单举例如下:
序列化_serialize

// jsoncpp
Json::Value root;

Json::Value value;
value["string"] = "hello world";
root.append(std::move(value));

Json::FastWriter writer;
std::string json = writer.write(root);

1
2
3
4
5
6
7
8
9
10
//rapidjson
rapidjson::Document doc;
Document::AllocatorType &alloc = doc.GetAllocator();

doc.SetArray(); //必须,否则断言错误
rapidjson::Value value(kObjectType); //或者value.SetObject();
value.AddMember("string", "hello world", alloc); //不能使用value["string"],会断言失败
doc.PushBack(value, alloc);

rapidjson::StringBuffer buffer; //对buffer内存的释放只能析构,使用clear方法只能改变size,不能改变capacity, 类似于std::vector
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
std::string json = buffer.GetString();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//json 输出
[
    {
        "string": "hello world"
    }
]
1
2
3
4
5
6
特别地,rapidjson::Document为文档对象,即根节点,rapidjson::Value为一般节点,归属于根节点;虽然rapidjson::Document继承自rapidjson::Value,但存在两个不同的节点表示和使用方式,并且全文涉及内存分配器,使用难度稍大一点,一不小心容易内存泄漏,千万记住doc一定要释放, 否则由doc的分配器分配出来的内存是不会自动释放的,如果应用一直服用一个doc,则top会清晰地观察到内存不断增长, 如果不关心中间对象,rapidjson提供了另一种直接的方式进行序列化,直接序列化,不经过JSON value, 如下:

//rapidjson
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
writer.StartArray(); //"["
writer.StartObject();// "{"
writer.key("string");// "string":
writer.String("hello world"); //"hello world"
writer.EndObject(); //"}"
writer.EndArray(); //"]"

std::string json = buffer.GetString();

1
2
3
4
5
6
7
8
9
10
11
12
反序列化_deserialize

//json 输入
[
    {
        "string": "hello world"
    }
]
1
2
3
4
5
6
//jsoncpp
std::string str;
Json::Value root;
Reader reader(Json::Features::strictMode());
if (reader.parse(str, root)) {
    //解析成功
    if (root.isArray() && !root.empty()) {
        auto size = root.size();
        for (uint32_t i = 0; i < size; i++)
        {
            if (root[i].isObject && root[i].isMember("string")) {
                str = root[i]["string"].isString() ? root[i]["string"].asString() : "";
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//rapidjson
std::string str;
rapidjosn::Document doc;
if (!doc.Parse(data, size).HasParseError()) {
   //解析成功
    if (doc.IsArray()) {
        auto arr = root.GetArray();
        for (auto &val : arr)
        {
            if (val.IsObject()) {
                auto it = val.FindMember("string");
                if (it != val.MemberEnd()) {
                    if (it->value.IsString()) { //等价于val["string"]
                        str = std::string(it->value.GetString(), it->value.GetStringLength);
                    }
                }
            } 
        }
    }
}

#if 0 //原位解析-更快
rapidjson::InsituStringStream iss(const_cast<char *>(json.c_str());
if (!doc.ParseStream<rapidjson::kParseDefaultFlags | rapidjson::kParseStopWhenDoneFlag | rapidjson::kParseInsituFlag>(iss).HasParseError()) {
    //解析成功
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
以上,jsoncpp和rapidjson反序列化流程基本一致,操作也很接近,但是rapidjson解析速度更快,辅以原位解析(in situ parsing), 性能可以做到极致。

3. 性能
测试版本:

rapidjson: 1.1.0
jsoncpp: 1.8.0
test.json
[{“map_key”:1,“id”:1,“desc”:“配置方案1”,“cycle”:100,“offset”:0,“coordPhase”:1,“timing”:[{“phase”:1,“time”:10,“status”:0,“barrier”:1},{“phase”:2,“time”:10,“status”:0,“barrier”:1},{“phase”:3,“time”:10,“status”:0,“barrier”:1},{“phase”:4,“time”:10,“status”:0,“barrier”:1},{“phase”:5,“time”:15,“status”:0,“barrier”:1},{“phase”:6,“time”:15,“status”:0,“barrier”:1},{“phase”:7,“time”:15,“status”:0,“barrier”:1},{“phase”:8,“time”:15,“status”:0,“barrier”:1},{“phase”:9,“time”:12,“status”:0,“barrier”:1},{“phase”:10,“time”:13,“status”:0,“barrier”:1},{“phase”:11,“time”:12,“status”:0,“barrier”:1},{“phase”:12,“time”:13,“status”:0,“barrier”:1},{“phase”:13,“time”:12,“status”:0,“barrier”:1},{“phase”:14,“time”:13,“status”:0,“barrier”:1},{“phase”:15,“time”:12,“status”:0,“barrier”:1},{“phase”:16,“time”:13,“status”:0,“barrier”:1},{“phase”:17,“time”:12,“status”:0,“barrier”:1},{“phase”:18,“time”:13,“status”:0,“barrier”:1},{“phase”:19,“time”:12,“status”:0,“barrier”:1},{“phase”:20,“time”:13,“status”:0,“barrier”:1},{“phase”:21,“time”:12,“status”:0,“barrier”:1},{“phase”:22,“time”:13,“status”:0,“barrier”:1},{“phase”:23,“time”:12,“status”:0,“barrier”:1},{“phase”:24,“time”:13,“status”:0,“barrier”:1},{“phase”:25,“time”:12,“status”:0,“barrier”:1},{“phase”:26,“time”:13,“status”:0,“barrier”:1},{“phase”:27,“time”:12,“status”:0,“barrier”:1},{“phase”:28,“time”:13,“status”:0,“barrier”:1},{“phase”:29,“time”:12,“status”:0,“barrier”:1},{“phase”:30,“time”:9,“status”:0,“barrier”:1},{“phase”:31,“time”:10,“status”:0,“barrier”:1},{“phase”:32,“time”:19,“status”:0,“barrier”:1},{“phase”:33,“time”:6,“status”:0,“barrier”:1},{“phase”:34,“time”:94,“status”:0,“barrier”:1},{“phase”:35,“time”:50,“status”:0,“barrier”:1},{“phase”:36,“time”:50,“status”:0,“barrier”:1},{“phase”:37,“time”:50,“status”:0,“barrier”:1},{“phase”:38,“time”:50,“status”:0,“barrier”:1},{“phase”:39,“time”:100,“status”:0,“barrier”:1}],“turn”:[[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16],[17,18,19,20,21,22,23,24],[25,26,27,28,29,30,31,32],[33,34],[35,36],[37,38],[39]]},…+64(重复64次) 126KB
测试主机arm-linux, 单核, 128M, 400MHZ, at91sam9x25(arm926)平台

arm-at91-linux-gnueabi-g++ -std=c++11 -Wall

-    JSON -> Value    Value -> T    JSON -> T    T -> Value    Value -> JSON    T -> JSON
jsoncpp    1s 778ms 593us    0s 426ms 634us    2s 262ms 984us    1s 375ms 353us    1s 376ms 462us    2s 867ms 207us
rapidjson    0s 255ms 710us    0s 165ms 277us    0s 426ms 507us    0s 180ms 312us    0s 146ms 775us    0s 249ms 457us
rapidjson(in situ)    0s 199ms 849us    -    0s 365ms 60us    -    -    -
arm-at91-linux-gnueabi-g++ -std=c++11 -Wall -O3

-    JSON -> Value    Value -> T    JSON -> T    T -> Value    Value -> JSON    T -> JSON
jsoncpp    0s 570ms 701us    0s 80ms 454us    0s 661ms 160us    0s 417ms 534us    0s 716ms 88us    1s 131ms 268us
rapidjson    0s 33ms 829us    0s 20ms 865us    0s 56ms 863us    0s 40ms 434us    0s 21ms 870us    0s 59ms 594us
rapidjson(in situ)    0s 31ms 48us    -    0s 55ms 364us    -    -    -
T: 结构体
JSON: 字符串
Value: json对象

4.总结
优先考虑使用性,选择jsoncpp;
优先考虑性能,速度,选择rapidjson;
均使用-O3优化。
————————————————
版权声明:本文为CSDN博主「samxfb」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_36623563/article/details/110491397

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值