目录
- Json是干什么的
- Json序列化代码
- Json反序列化代码
Json是干什么的
Json是一种轻量级的数据交换格式,也叫做数据序列化方式。Json完全独立于编程语言的文本格式来存储和表述数据。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
现在常用的是protobuf(但是较难),它更高效。
比如我们想要发送消息:
msg_type: 2
from: xxx
to: xxx
msg: xxxxxxx
我们通过网络发送,协议如果是TCP,就是字节流(TCP是面向字节流的协议,UDP是面向报文的协议),所以我们要把这个消息结构想办法进行数据序列化,转换成字节流或者字符流,进行发送,发送到远端。
远端接收到字节流/字符流之后,上报给应用,应用从字节流/字符流反序列化成原来的消息结构。
Json序列化代码
JSON for Modern C++这个三方库地使用很简单,将Json.hpp拖入C++项目中
#include "json.hpp"
using json = nlohmann::json; // 给nlohuann作用域下地json重新起一个简单的名字json
可以序列化整型和字符型
void fun1()
{json js;js["mag_type"] = 2;js["from"]="zhang san";js["to"]="li si";js["msg"] = "hello, what are you doing now?";cout << js <<endl;
}
输出如下,就和链式哈希表一样,是无序的:
{"from":"zhang san","mag_type":2,"msg":"hello, what are you doing now?","to":"li si"}
如果我们使用网络传输,传输的是char*,先将json转换成字符串,然后转换成char*。
string sendBuff = js.dump(); //dump()是json的内置函数,json数据对象 -> 序列化 json字符串
cout << sendBuff.c_str() <<endl;
这样的输出结果也是同样的
{"from":"zhang san","mag_type":2,"msg":"hello, what are you doing now?","to":"li si"}
可以序列化的内容不只是整型或者字符串,还可以是一些其他的类型,比如可以序列化数组,甚至还可以是个json类型。
void fun2(){json js;// 添加数组js["id"] = {1,2,3,4,5}; // 添加key-valuejs["name"] = "zhang san"; // 添加对象js["msg"]["zhang san"] = "hello world";js["msg"]["liu shuo"] = "hello china"; // 上面等同于下面这句一次性添加数组对象js["msg"] = {{"zhang san", "hello world"}, {"liu shuo", "hello china"}};cout << js << endl;
}
上面js对象的序列化结果是:
{"id":[1,2,3,4,5],msg":{"liu shuo":"hello china","zhang san":"hello world"},"name":"zhang san"}
可以把json类似的看成一个map表,放键值对的,但是值的类型可以是不相同的。
还可以序列化容器
void fun3(){json js;//直接序列化一个vector容器vector<int> vec;vec.push_back(1);vec.push_back(2);vec.push_back(3);js["list"] = vec;//序列化一个map容器map<int, string> m;m.insert({1, "huang"});m.insert({2, "lv"});m.insert({3, "hong"});js["path"] = m;cout << js << endl;
}
输出结果如下:
{"list":[1,2,3],"path":[[1,"huang"],[2,"lv"],[3,"hong"]]}
换成序列化后的json字符串输出还是一样的
string sendBuf = js.dump();
cout << sendBuf.c_str() << endl;-> {"list":[1,2,3],"path":[[1,"huang"],[2,"lv"],[3,"hong"]]}
Json反序列化代码
主要代码json jsbuf = json::parse(recvBuf);
反序列化fun1()
string recvBuf = fun1();//数据的反序列化 json字符串 -> 反序列化 数据对象(看作容器,方便访问)json jsbuf = json::parse(recvBuf);cout << jsbuf["msg_type"] << endl;cout << jsbuf["from"] << endl;cout << jsbuf["to"] << endl;cout << jsbuf["msg"] << endl;-> 2"zhang san""li si""hello, what are you doing now?"
反序列化fun2()
string recvBuf = fun2();
//数据的反序列化 json字符串 -> 反序列化 数据对象(看作容器,方便访问)
json jsbuf = json::parse(recvBuf);
cout << jsbuf["id"] << endl;
auto arr = jsbuf["id"];
cout << arr[2] << endl;auto msgjs = jsbuf["msg"];
cout << msgjs["zhang san"] << endl;
cout << msgjs["liu shuo"] << endl;-> [1,2,3,4,5]3"hello world""hello china"
反序列化fun3()
string recvBuf = fun3();
//数据的反序列化 json字符串 -> 反序列化 数据对象(看作容器,方便访问)
json jsbuf = json::parse(recvBuf);
vector<int> vec = jsbuf["list"]; //json对象里面的数组类型,直接放入vector容器当中
for(int &v : vec){cout << v << " ";
}
cout << endl;map<int, string> mymap = jsbuf["path"];
for(auto &p : mymap){cout << p.first << " " << p.second << endl;
}
-> 1 2 3 1 huang2 lv3 hong