Json简介及使用
Json简介及使用
一、Json简介
:是一种轻量级的),采用完全独立于编程语言的来存储和表示数据。 简洁和清晰的层次结构使得 Json 成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
例如:聊天软件的业务,消息种类分为很多种,例如:登录消息、注册消息、聊天消息、加好友消息等等,。而网络中TCP传输数据时为字节流,因此我们需要数据序列化将其转为字节流发送到对端主机,对端主机读取字节流上报应用服务,再将数据反序列化出来解析使用。

优秀的Json开源库JSON for Modern C++:由德国大牛 nlohmann 编写的在 C++ 下使用的 Json 库,具有以下优点:
直观的语法;
整个代码由一个头文件组成 json.hpp,没有子项目、依赖关系、复杂的构建系统,使用起来非常方便;
使用 C++ 11 标准编写,使用 Json 像使用 STL 容器一样;
STL 和 Json 容器之间可以相互转换;
所有类都经过严格的单元测试,覆盖了 100% 的代码,包括所有特殊的行为。此外,还检查了 Valgrind 是否有内存泄漏。为了保持高质量,该项目遵循核心基础设施倡议(CII)的最佳实践。
二、Json语法
2.1 Json语法
:它是,主要有以下特点:
在名称/值对的;
数据由
逗号 ,
;使用
反斜杆 \
来字符;大括号 {}
保存;中括号 []
保存,数组可以包含多个对象;
2.2 Json的两种结构:
对象:
大括号 {}
保存的对象是一个无序的名称/值对集合。一个对象以左括号 {
开始,右括号 }
结束。每个"键"后跟一个冒号 :
,名称/值对使用逗号 ,
分隔。数组:
中括号 []
保存的数组是值(value)的有序集合。一个数组以左中括号[
开始,右中括号 ]
结束,值之间使用逗号 ,
分隔。可以是括起来的或者,也可以是他们的。
2.3 书写格式
key : value格式,类似于我们C++中的map容器,十分简洁清晰,例如:
json js;
js["name"] = "xiaoming";
三、数据序列化实例
Json序列化: 在网络中,常用的数据传输序列化格式有XML、Json、ProtoBuf,在公司级别的项目中,大量的在使用ProtoBuf作为数据序列化的方式,它数据压缩编码传输,占用带宽小,同样的数据信息,是Json的1/10,XML的1/20,但是使用起来比Json稍复杂一些,学习成本较高,所以项目中我们选择常用的Json格式来打包传输数据。
#include "json.hpp"
using json = nlohmann::json;
3.1 普通数据序列化
//1、Json普通数据序列化
void test1() {
json js; //添加Json对象
js["msg_type"] = 2;
js["from"] = "zhangsan";
js["to"] = "lisi";
js["msg"] = "hello, good morning!";
cout << js << endl;
}
序列化输出Json字符串:

dump()
方法,将dict类型的数据转成str。
利用void test1() {
json js;
js["msg_type"] = 2;
js["from"] = "zhangsan";
js["to"] = "lisi";
js["msg"] = "hello, good morning!";
string sendBuf = js.dump();//Json数据对象 =》 Json字符串
cout << sendBuf.c_str() << endl;
}
输出**,可以在网络中进行**:

3.2 Json添加数组类型
//2、Json添加数组类型
void test2() {
json js;
js["id"] = {1, 2, 3, 4, 5} //添加数组
js["name"] = "zhangsan"; //添加key-value
js["msg"]["zhangsan"] = "good noon!";
js["msg"]["lisi"] = "good night!";
//添加Json对象,上面两句等同于此句一次性添加数组对象
js["msg"] = {{"zhangsan", "good noon!"}, {"lisi", "good night!"}};
cout << js << endl;
}

数组尽量使用vector可以动态地调整大小
3.3 容器序列化:
//3、容器序列化
void test3() {
json js;
//直接序列化一个vector容器
vector<int> vec;
vec.push_pack(1);
vec.push_pack(2);
vec.push_pack(3);
js["list"] = vec;
//直接序列化一个map容器
map<int, string> m;
m.insert({1, "黄山"});
m.insert({2, "华山"});
m.insert({3, "泰山"});
js["local"] = m;
cout << js << endl;
}

json::parse()
数据反序列化实例
四、parse : 解析
Json反序列化: 当我们从网络接收到字符串为Json格式时,可以用JSON for Modern C++ 直接反序列化取得数据或者直接反序列化出对象,甚至是容器。
4.1 普通数据反序列化
string test4() {
json js;
js["msg_type"] = 2;
js["form"] = "zhangsan";
js["to"] = "lisi";
js["msg"] = "good morning!";
string sendBuf = js.dump()
return sendBuf;
}
int main() {
string recvBuf = test4();
//反序列化,Json字符串 => 数据对象
json jsBuf = json::parse(recvBuf);
cout << jsbuf["msg_type"] << endl;
cout << jsbuf["from"] << endl;
cout << jsbuf["to"] << endl;
cout << jsbuf["msg"] << endl;
return 0;
}
反序列化输出结果如下,还保留了相应数据类型。

4.2 数组类型数据反序列化:
string test5() {
json js;
js["id"] = { 1,2,3,4,5 };
js["name"] = "zhangsan";
js["msg"] = {{"zhangsan", "good noon!"}, {"lisi", "good night!"}};
return js.dump();
}
int main() {
string recvBuf = test5();
json jsBuf = json::parse(recvBuf);
cout << jsBuf["id"] << endl;
auto jsMsg = jsBuf["msg"];
cout << jsMsg["zhangsan"] << endl;
cout << jsMsg["lisi"] << endl;
return 0;
}

容器反序列化
string test6() {
vector<int> vec = {1, 2, 3};
json js;
js["list"] = vec;
map<int, string> m = {{1, "黄山"},
{2, "华山"},
{3, "泰山"}};
js["local"] = m;
return js.dump();
}
int main() {
string recvBuf = test6();
json jsBuf = json::parse(recvBuf);
//将js对象中数组类型直接放入vector容器中
vector<int> vec = jsBuf["list"];
for(int v : vec) {
cout << v << " ";
}
cout << endl;
//将js对象中数组类型直接放入map容器中
map<int, string> mp = jsBuf["local"];
for(auto it : mp) {
cout << it.first << " " << it.second << endl;
}
cout << endl;
return 0;
}
