文章目录

      • 一、Json简介
      • 二、Json语法
      • 三、数据序列化实例
        • 3.1 普通数据序列化
        • 3.2 容器序列化
      • 四、数据反序列化实例
        • 4.1 普通数据反序列化
        • 4.2 容器反序列化

一、Json简介

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

优秀的Json开源库JSON for Modern C++:由德国大牛 nlohmann 编写的在 C++ 下使用的 Json 库,具有以下优点:
1、直观的语法;
2、整个代码由一个头文件组成 json.hpp,没有子项目、、依赖关系、复杂的构建系统,使用起来非常方便;
3、使用 C++ 11 标准编写,使用 Json 像使用 STL 容器一样;
4、STL 和 Json 容器之间可以相互转换;
5、所有类都经过严格的单元测试,覆盖了 100% 的代码,包括所有特殊的行为。此外,还检查了 Valgrind 是否有内存泄漏。为了保持高质量,该项目遵循核心基础设施倡议(CII)的最佳实践。

二、Json语法

Json语法:它是JavaScript 对象表示语法的子集,主要有以下特点:
1、数据在名称/值对中;
2、数据由逗号 , 分隔;
3、使用斜杆 \ 来转义字符;
4、大括号 {} 保存对象;
5、中括号 [] 保存数组,数组可以包含多个对象;

Json的两种结构:
1、对象: 大括号 {} 保存的对象是一个无序的名称/值对集合。一个对象以左括号 { 开始, 右括号 } 结束。每个”键”后跟一个冒号 :,名称/值对使用逗号 , 分隔。
2、数组: 中括号 [] 保存的数组是值(value)的有序集合。一个数组以左中括号[开始, 右中括号 ]结束,值之间使用逗号 , 分隔。值(value)可以是双引号括起来的字符串、数值、true、false、 null、对象或者数组,也可以是他们的嵌套类型。

书写格式: key : value格式,类似于我们C++中的map容器,十分简洁清晰,例如:

json js;js["name"] = "xiaoming";

三、数据序列化实例

Json序列化: 在网络中,常用的数据传输序列化格式有XML、Json、ProtoBuf,在公司级别的项目中,大量的在使用ProtoBuf作为数据序列化的方式,它数据压缩编码传输,占用带宽小,同样的数据信息,是Json的1/10,XML的1/20,但是使用起来比Json稍复杂一些,学习成本较高,所以项目中我们选择常用的Json格式来打包传输数据。

使用前准备:需要提前下载好Json.hpp,使用时引入头文件即可。

#include "json.hpp"using json = nlohmann::json;
3.1 普通数据序列化

1、Json进行普通数据序列化:

//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字符串:

2、Json序列化:利用dump()方法,将dict类型的数据转成str。

//1、Json普通数据序列化void test1(){json js; //添加Json对象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;}

输出string字符串,可以在网络中进行传输:

3、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!";js["msg"] = {{"zhangsan", "good noon!"}, {"lisi", "good night!"}}; //添加Json对象,上面两句等同于此句一次性添加数组对象cout << js << endl;}

序列化结果如下,输出结果一致的:

3.2 容器序列化

1、容器序列化:

//3、容器序列化void test3(){json js;//3.1 直接序列化一个vector容器vector<int> vec;vec.push_back(1);vec.push_back(2);vec.push_back(3);js["list"] = vec;//3.2 直接序列化一个map容器map<int, string> m;m.insert({1, "黄山"});m.insert({2, "华山"});m.insert({3, "泰山"});js["local"] = m;cout << js << endl;}

序列化结果如下:

四、数据反序列化实例

Json反序列化: 当我们从网络接收到字符串为Json格式时,可以用JSON for Modern C++ 直接反序列化取得数据或者直接反序列化出对象,甚至是容器。

4.1 普通数据反序列化

1、Json普通数据反序列化:利用parse()方法,从Json字符串反序列化为Json数据对象,类似于容器方便访问。

//4、Json普通数据反序列化string test4(){json js; //添加Json对象js["msg_type"] = 2;js["from"] = "zhangsan";js["to"] = "lisi";js["msg"] = "hello, good morning!";string sendBuf = js.dump(); //Json数据对象 =》 Json字符串return sendBuf;}int main(){string recvBuf = test4();json jsbuf = json::parse(recvBuf); //反序列化,Json字符串 => 数据对象cout << jsbuf["msg_type"] << endl;cout << jsbuf["from"] << endl;cout << jsbuf["to"] << endl;cout << jsbuf["msg"] << endl;return 0;}

反序列化输出结果如下,还保留了相应数据类型。

2、其它类型数据反序列化:

//5、Json其它类型数据反序列化string test5(){json js;js["id"] = {1, 2, 3, 4, 5}; //添加数组js["name"] = "zhangsan"; //添加key-value js["msg"]["zhangsan"] = "good noon!";js["msg"]["lisi"] = "good night!";js["msg"] = {{"zhangsan", "good noon!"}, {"lisi", "good night!"}}; //添加Json对象,上面两句等同于此句一次性添加数组对象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;}

反序列化结果如下:

4.2 容器反序列化

1、容器反序列化:

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

反序列化结果如下:

以上就是我们基于用JSON for Modern C++库的一个简单使用了,如有错误还望批评指正。