Json是一种轻量级的数据交换格式(也叫数据序列化方式)。
也就是说,我们在数据的传输上其实已经被序列化了,等发到服务器或者是发到客户端的时候,我们需要把它反序列化成json。
json长什么样子可以直接去百度即可。
在网络中,常用的数据传输序列化格式有XML,Json,ProtoBuf,在公司级别的项目中,大量的在使用 ProtoBuf作为数据序列化的方式,以其数据压缩编码传输,占用带宽小,同样的数据信息,是Json的 1/10,XML的1/20,但是使用起来比Json稍复杂一些,所以项目中我们选择常用的Json格式来打包传输 数据。
Json第三方库
JSON for Modern C++ 是一个由德国大牛 nlohmann 编写的在 C++ 下使用的 JSON 库。
具有以下特点
-
直观的语法
-
整个代码由一个头文件组成 json.hpp,没有子项目,没有依赖关系,没有复杂的构建系统,使用 起来非常方便
-
使用 C++ 11 标准编写
-
使用 json 像使用 STL 容器一样
-
STL 和 json 容器之间可以相互转换
-
严谨的测试:所有类都经过严格的单元测试,覆盖了 100% 的代码,包括所有特殊的行为。此 外,还检查了 Valgrind 是否有内存泄漏。为了保持高质量,该项目遵循核心基础设施倡议(CII) 的最佳实践
使用的时候,我们这样即可:
#include "json.hpp"
using json = nlohmann::json;
Json数据序列化
就是把我们想要打包的数据,或者对象,直接处理成Json字符串。简单理解,json字符串就是由大括号括起来的键值对。和我们C++里面的无序关联容器比较像,其实它底层就是使用链式哈希表进行存储。
案例一:Json完成字符串的序列化
#include "json.hpp"
using json = nlohmann::json;
#include <iostream>
using namespace std;
//json序列化实例1
void func1() {
json js;
//想要组装的数据格式
js["msg_type"] = 2;
js["from"] = "zhang san";
js["to"] = "li si";
js["msg"] = "hello, what are you doing now?";
//直接被序列化成一个js
cout << js << endl;
}
int main () {
func1();
return 0;
}
打印效果如下:
{"from":"zhang san","msg":"hello, what are you doing now?","msg_type":2,"to":"li si"}
我们要注意他的存储是无序的,并不是说我第一个插msg_type
,第一个显示的就是msg_type
我现在想把Json字符串通过网络发送出去,我肯定要把它转成字符串类型,那么怎么把Json类型里面包含的Json字符串(序列化后的数据)转换为字符串进行发送呢?
案例二:将Json字符串转换为std::string
#include <string>
string sendBuf = js.dump();
cout << sendBuf.c_str << endl;
如果我们通过网络传输,肯定是吧 string 转换成 char*。
最后打印输出的结果和上面是一样的。
案例二:序列化
他可以序列化更加复杂的内容,
首先其中的key对应的 value 本身可以是普通的类型,也可以是字符串类型,甚至可以是数组类型。
void func2() {
json js; // 添加数组
js["id"] = {1,2,3,4,5};
// 添加key-value
js["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["msg"]["zhang san"] = "hello world";
js["msg"]["liu shuo"] = "hello china"
也就是说我们的 js["msg"]
字符串仍然是一个 Json字符串,所以我们还可以访问 js["msg"]
它的 key 和 value : js["msg"]["zhang san"]
也就是说某个键的值可以是任何类型。
案例三:序列化容器
这是Json非常强大的功能,它可以直接序列化容器。
在以下示例中,他直接序列化容器 vector 和 map:
void func3() {
json js;
// 直接序列化一个vector容器
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(5);
js["list"] = vec;
// 直接序列化一个map容器
map<int, string> m;
m.insert({1, "挺好的?"});
m.insert({2, "华山"});
m.insert({3, "泰山"});
js["path"] = m;
string sendBuf = js.dump(); // json数据对象 =》序列化 json字符串
cout<<sendBuf<<endl;
//return sendBuf;
}
打印结果如下:
{"list":[1,2,5],"path":[[1,"挺好的?"],[2,"华山"],[3,"泰山"]]}
这个序列化结果显示,Json吧 vector 直接序列化成了数组,把 map 序列化成了“数组里面套数组”。
现在我们把它进行序列化:
string sendBuf = js.dump(); //json数据对象=》序列化 json字符串
cout << sendBuf.c_str() << endl;
这样我们可以把它通过网络发送