nlohmann/json官方网站
https://github.com/nlohmann/json
https://json.nlohmann.me/api/basic_json/
背景
2022.09
nlohmann/json官方序列化,提供了宏NLOHMANN_DEFINE_TYPE_INTRUSIVE;
它支持多层嵌套,但对于指针无法序列化;
实际上这个宏定义就是在class中增加了to_json和from_json函数,我们可以自己去实现一下即可;
示例
TreeNode.hpp
class TreeNode;
using TreeNodePtr = std::shared_ptr<TreeNode>;
using ShaJson = nlohmann::json;
class TreeNode {
public:
std::string id;
std::string name;
std::list<TreeNodePtr> children;
friend void to_json(nlohmann::json& nlohmann_json_j, const TreeNode& nlohmann_json_t)
{
nlohmann_json_j["id"] = nlohmann_json_t.id;
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["children"] = nlohmann::json::array();
for(TreeNodePtr x : nlohmann_json_t.children)
{
std::cout << x->name << std::endl;
nlohmann::json jsonTemp;
to_json(jsonTemp, *x);
nlohmann_json_j["children"].push_back(jsonTemp);
}
}
friend void from_json(const nlohmann::json& nlohmann_json_j, TreeNode& nlohmann_json_t)
{
nlohmann_json_t.id = nlohmann_json_j.at("id");
nlohmann_json_t.name = nlohmann_json_j.at("name");
nlohmann::json arrayTemp = nlohmann::json::array();
arrayTemp = nlohmann_json_j.at("children");
for (nlohmann::json& el : arrayTemp) {
TreeNodePtr treeNode(new TreeNode());
from_json(el, *treeNode);
nlohmann_json_t.children.push_back(treeNode);
}
}
};
测试代码
int main() {
std::cout << "Hello, World!" << std::endl;
TreeNodePtr treeNode(new TreeNode());
treeNode->name = "node1";
TreeNodePtr treeNode2(new TreeNode());
treeNode2->name = "node2";
TreeNodePtr treeNode3(new TreeNode());
treeNode3->name = "node3";
treeNode->children.push_back(treeNode2);
treeNode2->children.push_back(treeNode3);
ShaJson json = *treeNode;
std::cout << json.dump(4) << std::endl;
json = ShaJson::parse(json.dump());
TreeNodePtr temp(new TreeNode());
*temp = json.get<TreeNode>();
std::cout << json.dump(4) << std::endl;
return 0;
}
智能指针支持
FuncInfo.hpp
实体类
class FuncInfo {
public:
std::string funcId;
std::string funcName;
std::string parentId;
};
using FuncInfoPtr = std::shared_ptr<FuncInfo>;
FuncTreeNode.hpp
class FuncTreeNode;
using FuncTreeNodePtr = std::shared_ptr<FuncTreeNode>;
class FuncTreeNode {
public:
std::string funcId;
std::string funcName;
std::string parentId;
std::vector<FuncTreeNodePtr> childFuncs;
static FuncTreeNodePtr createTree(std::vector<FuncInfoPtr> &funcInfos, FuncTreeNodePtr root){
std::vector<FuncTreeNodePtr> children;
for(FuncInfoPtr x : funcInfos){
if(x->parentId == root->funcId){
children.push_back(createTree(funcInfos, x));
}
}
root->childFuncs = children;
return root;
}
static std::vector<FuncTreeNodePtr> createForest(std::vector<FuncInfoPtr> funcInfos) {
// 存放多个根节点
std::vector<FuncTreeNodePtr> rootList;
// 找到根节点,并放到rootList中
for (int i = 0; i < funcInfos.size(); i++) {
bool hasParent = false;
for (int j = 0; j < funcInfos.size(); j++) {
if (funcInfos[i]->parentId == funcInfos[j]->funcId) {
hasParent = true;
break;
}
}
if (hasParent == false) {
FuncTreeNodePtr root(new FuncTreeNode());
root->funcId = funcInfos[i]->funcId;
root->parentId = funcInfos[i]->parentId;
root->funcName = funcInfos[i]->funcName;
rootList.push_back(root);
}
}
// 从每个根节点开始构建树
for(FuncTreeNodePtr root : rootList){
createTree(funcInfos, root);
}
return rootList;
}
// 序列化
friend void to_json(nlohmann::json& nlohmann_json_j, const FuncTreeNode& nlohmann_json_t)
{
nlohmann_json_j["funcId"] = nlohmann_json_t.funcId;
nlohmann_json_j["funcName"] = nlohmann_json_t.funcName;
nlohmann_json_j["childFuncs"] = nlohmann::json::array();
for(FuncTreeNodePtr x : nlohmann_json_t.childFuncs)
{
nlohmann::json jsonTemp;
to_json(jsonTemp, *x);
nlohmann_json_j["childFuncs"].push_back(jsonTemp);
}
}
friend void from_json(const nlohmann::json& nlohmann_json_j, FuncTreeNode& nlohmann_json_t)
{
nlohmann_json_t.funcId = nlohmann_json_j.at("funcId");
nlohmann_json_t.funcName = nlohmann_json_j.at("funcName");
nlohmann::json arrayTemp = nlohmann::json::array();
arrayTemp = nlohmann_json_j.at("childFuncs");
for (nlohmann::json& el : arrayTemp) {
FuncTreeNodePtr treeNode(new FuncTreeNode());
from_json(el, *treeNode);
nlohmann_json_t.childFuncs.push_back(treeNode);
}
}
// 智能指针版本
friend void to_json(nlohmann::json& nlohmann_json_j, const FuncTreeNodePtr nlohmann_json_t)
{
nlohmann_json_j["funcId"] = nlohmann_json_t->funcId;
nlohmann_json_j["funcName"] = nlohmann_json_t->funcName;
nlohmann_json_j["childFuncs"] = nlohmann::json::array();
for(FuncTreeNodePtr x : nlohmann_json_t->childFuncs)
{
nlohmann::json jsonTemp;
to_json(jsonTemp, *x);
nlohmann_json_j["childFuncs"].push_back(jsonTemp);
}
}
friend void from_json(const nlohmann::json& nlohmann_json_j, FuncTreeNodePtr nlohmann_json_t)
{
nlohmann_json_t->funcId = nlohmann_json_j.at("funcId");
nlohmann_json_t->funcName = nlohmann_json_j.at("funcName");
nlohmann::json arrayTemp = nlohmann::json::array();
arrayTemp = nlohmann_json_j.at("childFuncs");
for (nlohmann::json& el : arrayTemp) {
FuncTreeNodePtr treeNode(new FuncTreeNode());
from_json(el, *treeNode);
nlohmann_json_t->childFuncs.push_back(treeNode);
}
}
};
测试代码
森林
int main() {
std::cout << "Hello, World!" << std::endl;
//StringUtils::test20220925();
FuncTreeNodePtr ptr1(new FuncTreeNode());
ptr1->funcName = "node1";
FuncTreeNodePtr ptr2(new FuncTreeNode());
ptr2->funcName = "node2";
FuncTreeNodePtr ptr3(new FuncTreeNode());
ptr3->funcName = "node3";
ptr1->childFuncs.push_back(ptr2);
ptr2->childFuncs.push_back(ptr3);
ShaJson json = *ptr1;
//std::cout << json.dump() << std::endl;
std::vector<FuncInfoPtr> funcInfos;
FuncInfoPtr funcInfoPtr1(new FuncInfo());
funcInfoPtr1->funcId = "1";
funcInfoPtr1->parentId = "-1";
FuncInfoPtr funcInfoPtr2(new FuncInfo());
funcInfoPtr2->funcId = "2";
funcInfoPtr2->parentId = "-1";
FuncInfoPtr funcInfoPtr3(new FuncInfo());
funcInfoPtr3->funcId = "3";
funcInfoPtr3->parentId = "2";
FuncInfoPtr funcInfoPtr4(new FuncInfo());
funcInfoPtr4->funcId = "4";
funcInfoPtr4->parentId = "3";
funcInfos.push_back(funcInfoPtr1);
funcInfos.push_back(funcInfoPtr2);
funcInfos.push_back(funcInfoPtr3);
funcInfos.push_back(funcInfoPtr4);
std::vector<FuncTreeNodePtr> forest = FuncTreeNode::createForest(funcInfos);
std::string str;
str += "[";
for(FuncTreeNodePtr x : forest)
{
ShaJson jsonOut = *x;
str += jsonOut.dump();
str += ",";
}
str += "]";
std::cout << str << std::endl;
ShaJson jsonx = forest;
std::cout << jsonx.dump() << std::endl;
return 0;
}
输出
Hello, World!
[{“childFuncs”:[],“funcId”:“1”,“funcName”:“”},{“childFuncs”:[{“childFuncs”:[{“childFuncs”:[],“funcId”:“4”,“funcName”:“”}
],“funcId”:“3”,“funcName”:“”}],“funcId”:“2”,“funcName”:“”},]
[{“childFuncs”:[],“funcId”:“1”,“funcName”:“”},{“childFuncs”:[{“childFuncs”:[{“childFuncs”:[],“funcId”:“4”,“funcName”:“”}
],“funcId”:“3”,“funcName”:“”}],“funcId”:“2”,“funcName”:“”}]
json结构
[
{
"childFuncs":[
],
"funcId":"1",
"funcName":""
},
{
"childFuncs":[
{
"childFuncs":[
{
"childFuncs":[
],
"funcId":"4",
"funcName":""
}
],
"funcId":"3",
"funcName":""
}
],
"funcId":"2",
"funcName":""
}
]