先上链接:https://pan.baidu.com/s/1Tb7Vv7osGqdeG0ZoKOU6_g?pwd=btn5
2024.04.09:github上也更新了,链接在:https://github.com/neoatomic-repo/cxx-json-serialize
尽管本文实现的扩展是针对C++应用的,大家都会用得上;但从实际业务场景上,也是为转到从事国产化开发的同学们,提供一个便利,你们懂的。
如果你看完了本文、并且下载源码包觉得用着OK,记得点赞让我知道哈(git不容易连上:()。
准确的讲,本文的主题是“JSON序列化:应用于C++对象”。
本应用扩展的实现基于c++11、cJSON。(有了它,可以替换QJson了 ,比如QPluginLoader里面的json操作就挺麻烦的)。
CJS前缀: c++ JSON Serialize
背景与问题
在C++中,即便于使用cJSON、或者QJson等,一般也只是能从一个json字符串,得到一系列层次化的json键值对。
比如,以jsonStr = "{\"name\":\"Rich\",\"id\":123}"这串代表json格式的字符串为例,使用cJSON库中的cJSON_Parse进行解析后,会得到一个cJSON对象jsonObj,它的成员状态为:
jsonObj["name"] == "Rich"
jsonObj["id"] == 123
然而,我们其实更需要的是像java中的一些工具库那样(比如阿里的fastjson等),能把jsonStr直接反序列化为我们在业务层定义的某个类/结构体对象实例;或者把某个类/结构体对象实例,直接序列化为jsonStr字符串。
经常使用C++的同学,可能对java里的序列化/反序列化的使用不熟悉,从而惧怕或者不明就里。然而,一方面基于反射实现的这种便捷,综合效率上,已经经过了长久验证;另一方面,更明朗的,我们以fastjson为例来说明,其在java里的基本使用如下:
package com.neoatomic.example;
import com.alibaba.fastjson.*;
public class App {
// 假设定义了一个(java里)的类JPerson,对其进行序列化操作:
public static JPerson {
public String name;
public Integer id;
}
public static void main(String[] args) {
JPerson personInfo;
personInfo.name = "Poly";
personInfo.id = 12;
System.out.println(JSON.toJSONString(personInfo)); // 这里输出:"{\"name\":\"Poly\",\"id\":12}"
String jsonStr = "{\"name\":\"Rich\",\"id\":123}";
personInfo = JSON.parseObject(jsonStr, JPerson.class);
// 现在,personInfo.name.equals("Rich"); personInfo.id == 123
}
}
如上,在java里,由于有反射,所以fastjson能够提供便利的接口toJSONString、parseObject,以方便的对某个对象进行序列化操作(或者将一串json字符串反序列化以填充这个对象的成员变量值)。
所以,问题来了,如何在C++里也像java一样,便利的对结构体(或者类)对象进行json的序列化操作呢?
方案
由于C++里,目前的标准库仍然没有反射,并且为了让代码在遗留的历史OS上容易的编译,我们经常还是会使用c++11、c++14,所以,实现这种便利,不应该使用最新的C++标准库,否则仍然会把麻烦留给使用者。