前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ijst:基于反射的 C++ JSON 反序列化库

ijst:基于反射的 C++ JSON 反序列化库

原创
作者头像
h46incon
修改2018-08-20 19:26:55
3.1K0
修改2018-08-20 19:26:55
举报
文章被收录于专栏:知了知了

ijst

Github repo: github.com/h46incon/ijst

ijst (iJsonStruct) 一个是 C++ Json 序列化/反序列化库:

  • 只需定义一次结构体,无须重复添加元信息。
  • 支持 Getter Chaining,可以很简单地访问路径较深的字段。
  • 支持 unknown 字段和可选字段。
  • 支持 UTF-8, UTF-16, UTF-32 编码。
  • 轻量:header-only,仅依赖 stl 和 RapidJSON
  • 兼容 C++ 98/03。支持 C++ 11 特性,如右值构造、extern template 等。
  • 反序列失败时,会有详细的错误信息。

使用

安装

  1. 安装 RapidJSON v1.1.0 以上版本(将其加入 header 搜索路径即可)。
  2. include/ijst 文件夹复制进工程。

单元测试(可选)

可通过以下命令安装依赖并执行单元测试:

代码语言:txt
复制
cd IJST
git submodule update --init
mkdir CMakeBuild && cd CMakeBuild
cmake ..
make
./unit_test/unit_test

基本使用

定义结构体
代码语言:txt
复制
#include <ijst/ijst.h>
#include <ijst/types_std.h>
#include <ijst/types_container.h>
using namespace ijst;

//*** 需要反序列化的 JSON 字符串
const std::string jsonStr = R"(
{
    "int_val": 42, 
    "vec_val": ["str1", "str2"], 
    "map_val": {"k1": 1, "k2": 2}
})";

//*** 定义一个 ijst 结构体:
IJST_DEFINE_STRUCT(
    // 结构体名字
    JsonStruct
    // 定义字段
    , (T_int, iVal, "int_val", 0)  
    , (IJST_TVEC(T_string), vecVal, "vec_val", 0)
    , (IJST_TMAP(T_uint64), mapVal, "map_val", 0)
);

//*** 默认情况下会生成这样的类:
/*
class JsonStruct {
public:
    ijst::Accessor _;   // 通过这个对象进行序列化等操作
    int iVal; 
    std::vector<std::string> vecVal; 
    std::map<std::string, uint64_t> mapVal; 

private:
    //... Some private methods
};
*/
字段访问及(反)序列化
代码语言:txt
复制
//*** 定义一个 JsonStruct 对象
JsonStruct jStruct;

//*** 反序列化
int ret = jStruct._.Deserialize(jsonStr);
assert(ret == 0);

//*** 访问字段
assert(jStruct.iVal == 42);
assert(jStruct.vecVal[0] == "str1");
assert(jStruct.mapVal["k2"] == 2);

//*** 序列化
std::string strOut;
ret = jStruct._.Serialize(strOut);
assert (ret == 0);

Getter Chaining

如果所需访问的字段的路径比较深的时候,为避免累赘的判断,可使用 get_* 方法,比如:

代码语言:txt
复制
//*** 和 IJST_DEFINE_STRUCT 类似
IJST_DEFINE_STRUCT_WITH_GETTER(
    StIn
    , (T_int, iData, "i", ijst::FDesc::Optional)
    , (IJST_TVEC(T_int), vecData, "vec", ijst::FDesc::Optional)
    , (IJST_TMAP(T_int), mapData, "map", ijst::FDesc::Optional)
)

//*** 默认情况下会生成这样的结构体:
/*
class JsonStruct {
public:
    //... 普通的字段,同 IJST_DEFINE_STRUCT
    
    // Getters
    ijst::Optional<int> get_iData();
    ijst::Optional<std::vector<int> > get_vecData();
    ijst::Optional<std::map<std::string, int> > get_mapData();
private:
};
*/

IJST_DEFINE_STRUCT_WITH_GETTER(
    StOut
    , (IJST_TST(StOut), stIn, "inner", ijst::FDesc::Optional)
)
StOut st;

//*** 可以通过连串的 get_* 尝试直接访问字段,而不用关注路径的中间节点是否存在
// 下行语句可访问 "/stIn/vecData/2"
// int* pData = st.get_stIn()->get_vecData()[2].Ptr();
// 即:
int* pData = st         // StOut 对象
    .get_stIn()         // 访问 stIn 字段
    ->get_vecData()     // 访问 vecData 字段,注意需使用 -> 操作符
    [2]                 // 访问数组中第2个元素
    .Ptr();             // 获取最后结果的地址
assert (pData == NULL);

// 如果路径中的每个字段都是 kValid 的,且 vector 的下标存在,则最终得到的指针会指向该字段:
// int* pData = st.get_stIn()->get_vecData()[2].Ptr() == &st.stIn.vecData[2];

性能

ijst 底层使用的是 RapidJSON,其本身具有优秀的性能。

ijst 因有额外的工作,会带来一些性能上的开销,但也比常用的 JsonCpp 快上不少:

Library

序列化

反序列化

RapidJSON

14

10

ijst

16

23

JsonCpp

128

109

测试环境:Corei7-4790_3.60GHz_vc2017_win7x64,测试代码: nativejson-benchmark

注:不同环境测得的性能会有差异,一般而言,ijst 的序列化性能和 RapidJSON 相似,反序列化性能为其 1/4 ~ 1/2。

详细说明

详请请移步 Github : github.com/h46incon/ijst

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ijst
  • 使用
    • 安装
      • 单元测试(可选)
        • 基本使用
          • 定义结构体
          • 字段访问及(反)序列化
        • Getter Chaining
        • 性能
        • 详细说明
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档