tp数组转为json_C++ 轻量级对象JSON序列化实现

本文介绍了一种使用jsoncpp库简化C++中JSON序列化与反序列化的方案,通过设计通用模板函数,实现对象与JSON字符串间的快速转换。

b42ce8b8947e5c69488c5ec9f3848573.png

背景:

在项目里经常遇到对象和json字符串的相互转换这类问题,在大多数程序里,一般这个问题都比较有比较好的解决方法,往往一个函数搞定。但是到了c++这边却需要我们手撸json库一个一个字段初始化/序列化。如果这时候有一个函数 可以一行代码 unmarshal /marshal 对象岂不是很方便?本文以jsoncpp库为基础,设计这样一个可以支持这种功能的函数,下面进入正题~

设计思路

以unmarshal 为例,我们最终的函数是打造两个这样的模板函数 :

一个从string 的josn直接反序列化对象,一个从jsoncpp库的json对象,反序列化对象。

template

由于json是具有自递归结构的,所以在设计时,应该也是以递归的方式解决复杂的组合类,我们可以简单的把程序中的变量分为下面几类:

d1cd0fe710fdfd7aa117ed18013d2d7e.png

这样我们只需要把这几个场景的 Unmarshal实现了,整体的Unmarshal也就实现了。模板设计的类图应该和我们的分类相对应:

8eb9e00cfd4d66085a97d78fc2c1e4f4.png

在实现中要注意以下几点:

1、每个分类的Unmarshal模板具有排他性,也就是说基本类型在编译期间只能匹配解析基本类型的模板

2、由于1的保证和这些模板函数名称都是Unmarshal,所以他们之间可以相互嵌套调用对方。

3、指针、和原生数组会涉及到空间分配和长度检测会使得情况变得复杂,本次设计支持的范围不包含对指针、原生数组的支持。

匹配基本类型的Unmarshal模板

//只能解析基本类型 int long bool float double string 的一组模板

匹配stl容器/其他第三方类库的Unmarshal模板

//只能匹配 vector<T> map<string,T> map<long,T> map<int,T> 的一组模板

匹配自定义struct/class的Unmarshal模板

实现一组只能匹配自己定义的struct/class 就需要我们定义的对象有一些特殊的标志,才能被模板函数识别。在这里选择给我们自己定义的类都实现public的unmarshal方法(实现方式后面讲),这样当编译时发现一个对象含有 public的 unmarshal方法时,就知道使是我们自己定义的类,然后就调用特定的模板函数,这里用到到了一个C++的语法 SFINAE(Substitution Failure Is Not An Error) 和std库中enable_if

我们先来看一下C++ std库中 enable_if 的简要实现:

// 版本1 一个空的enable_if 结构体

SFINAE 准则就是匹配失败并不是错误,如果编译器在匹配一个模板时引发了错误,这时候编译器应当尝试下一个匹配,而不应该报错中止。利用这条规则和enable_if,解析我们自己struct/class Umarshal模板设计如下:

// 检测一个类 是否含有非静态非重载的unmarshal方法

好了,至此我们对三种基本类型的Umarshal函数设计好了,这时候任意一个T类型 在调用Unmarshal时,最终会与上面三种其中一个匹配。json 为string的可以利用上面的Unmarshal再封装一个版本:

template 

接下来我们看如何在自定义的类中实现unmarshal函数:

//假设有一个People对象,有3个field需要反序列化,根据上面的要求,可能需要我们自己编写unmarshal如下

显然如果field数量很多,就很麻烦,而且解析每个field时,代码格式非常相似,是否存在一个宏可以自动生成呢?答案是肯定的。talk is cheap,show me the code ,上代码!

struct 

测试

我们的Umarshal 和 Marshal函数编写好了,现在测试一下吧:

场景:有一个map对象存着教师的信息,每个教师又保存着ta教学生信息,数据结构定义如下:

struct 

测试代码:

// 对应于结构 map<string,Teacher> 的json

完整例子地址:https://git.xiaojukeji.com/sunriseyangxin/easyjson.git

作者:杨昕


  • 现在注册滴滴云,得10000元立减红包
  • 8月特惠,1C2G1M云服务器 9.9元/月限时抢
  • 滴滴云使者专属特惠,云服务器低至68元/年
  • 输入大师码【7886】,GPU全线产品9折优惠
滴滴云-为开发者而生​www.didiyun.com
9b8a3c128f32733cf74792f9268c7b5a.png
滴滴云使者​www.didiyun.com
9b8a3c128f32733cf74792f9268c7b5a.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值