string类型的json串取值_json之C++静态解析

所谓静态解析,就是将待解析字段,在C++中提前定义,格式类似于结构体,直接将解析出的内容放入字段中,这样和将字段内容解析到容器中相比,取值只有O(1)的时间复杂的,无需构造容器,解析无类型转换比较过程,缺点就是不太灵活。

关于json协议标准​www.ecma-international.org

要解析json数据需要那些元信息?

吃不到葡萄我会酸:C++ 元数据收集​zhuanlan.zhihu.com
52fa913409e66b86d4e7a9e6958661fe.png

为了保证解析效率足够高效,这里不会去收集字段的类型信息,而是通过收集其对应的操作函数入口来对json数据进行高效解析。

我们先来看看,在非宏编程状态下我们大概要怎样来怎样来解析一个数据

class Msg {
public:
 int a;
private:
 bool serialize_a() {
              serialize<int>(&a);
       }
 bool unserialize_a() {
              unserialize<int>(&a);
       }
};

所以经过抽象后,我们的元数据结构定义如下:

struct data_impl_t {
 void count_func_pointer_len() {}
 char unserialize[sizeof(&data_impl_t::count_func_pointer_len)];
 char serialize[sizeof(&data_impl_t::count_func_pointer_len)];
};
static std::unordered_map<no_copy_string, data_impl_t> fields;

先来解释一下为什么 data_impl_t 中会有一个空函数count_func_pointer_len,其实在不同的编译环境中,成员函数的地址大小是有差异的,在linux下sizeof(&data_impl_t::count_func_pointer_len) = 8,而在windows下这个值为4。

其实在最开始的时候我是用模板来定义元数据结构的,由于每个结构都会生成相应的的data_impl_t结构,这样导致的最大问题是生成的代码量比较大,同时比较费编译时间,所以使用了上面这种去模板化的方式来实现,只是会比较晦涩一点。

template<class T>
struct data_imple_t {
 typedef size_t(T::*unserialize_t)(const char*, size_t);
 typedef void(T::*serialize_t)(string &res);
 unserialize_t unserialize;
 serialize_t serialize;
};
项目已开源,源码可参考​github.com

来看看和repidjson的性能比较,以下为简单测试数据

{ "d":1.7976931348623157 }
{ "d":1.7976931348623157,"b" : "afsf","c" : [123,456],"f" : {"r":false,"r2" : true,"n" : null} }

d4bd49841fe2c86a75332c7552766321.png

如上图可见在处理简单高频json数据的时候,staticJson 的性能高出 rapidJson 至少一倍,其实在实际项目中使用得比较多的也是简单高频协议,以上可见静态解析的优势,缺点的话就是会牺牲一定的编译时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值