382-Json的介绍和使用

Json的介绍和使用

Json是一种轻量级的数据交换格式(也叫数据序列化方式)。Json采用完全独立于编程语言文本格式存储和表示数据。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
也就是说,客户端如果是C++写的,服务器是Java写的,没关系,大家都认识Json,虽然在整个网络中,不同的部件是不同的语言开发的,但是都认识Json,所以大家之间用Json交流就可以了,不管是什么语言开发的,你想把数据发给我,你就把数据序列化成Json字符串,我收到Json字符串时,就把Json字符串反序列化成我这个主机所用的语言能认识的消息体

我们在做聊天服务器项目的时候,比如说,我们发送一个聊天的消息,消息的种类很多,用msg_type区分,是登录消息,注册消息,聊天消息,还是加好友,群组的消息。from来自哪里,to给谁说的,msg消息的内容。

msg_type:2
from:xxx
to:xxx
msg:xxx

大致为上述的结构,但是我们通过网络TCP发送的都是字节流,所以对于这样的消息结构,我们要进行数据的序列化(转成json字节流发送到网络)和反序列化(远端接收到字节流,上报给应用,应用把json字节流反序列化成这样的消息结构)。

xml节点元素和标签特别多,浪费空间,现在用protobuf和json多。

一个优秀的Json三方库

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

包含json头文件

在网络中,常用的数据传输序列化格式有XML,Json,ProtoBuf,在公司级别的项目中,大量的在使用ProtoBuf作为数据序列化的方式,以其数据压缩编码传输,占用带宽小,同样的数据信息,是Json的1/10,XML的1/20,但是使用起来比Json稍复杂一些。
在基于RPC服务的分布式TCP网络通信框架的项目中,我使用的是protobuf的序列化和反序列化。所以,在基于muduo和nginx的集群聊天服务器项目中,我想学习json,采用json。

下面列举一些项目中用到的有关Json数据的序列化和反序列化代码,仅供参考!JSON for Modern C++这个三方库的使用非常简单,如下所示:

#include "json.hpp"
using json = nlohmann::json;

Json数据序列化

我们在linux下的vscode进行编程。
我在chatserver文件夹下创建一个test文件夹,在test文件夹里面创建一个testjson的文件夹,专门用于json的实践。

在这里插入图片描述
我们在testjson文件夹下创建文件:testjson.cpp
我们把json.hpp下载下来拉到linux中,移到testjson文件夹里面。
在这里插入图片描述
在这里插入图片描述
json序列化示例1( 普通数据序列化)
接下来我们书写testjson.cpp

#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
void func1()
{
    json js;//定义一个json类型的对象//添加数组
    js["msg_type"] = 2;
    js["from"] = "linzeyu";
    js["to"] = "zhang san";
    js["msg"] = "hello, are you ok now?";
    
    cout<<js<<endl;
}

int main()
{
    func1();
    return 0;
}

保存,运行
在这里插入图片描述
有键,有值
但是是无序的哦! 底层链式哈希表

我们做集群聊天服务器项目,是为了把json转成字符串通过网络发送出去。

#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
string func1()
{
    json js;
    js["msg_type"] = 2;
    js["from"] = "zhang san";
    js["to"] = "li si";
    js["msg"] = "hello, what are you doing now?";

    string sendBuf = js.dump();//输出的意思 
    //cout<<sendBuf.c_str()<<endl;//转成char*
    return sendBuf;
}

json序列化示例2(数组)
我们书写testjson.cpp
json的键可以是整数类型,字符串类型,还可以是数组类型。

//json序列化示例2
string 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;
    return js.dump();
}
#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
string func1()
{
    json js;//定义一个json类型的对象//添加数组
    js["msg_type"] = 2;
    js["from"] = "linzeyu";
    js["to"] = "zhang san";
    js["msg"] = "hello, are you ok now?";
 
    string sendBuf = js.dump();//输出的意思 
    //cout<<sendBuf.c_str()<<endl;//转成char*
    return sendBuf;
}

//json序列化示例2
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;
    //return js.dump();
}

int main()
{
    //func1();
    func2();
    return 0;
}

运行
在这里插入图片描述

json序列化示例3(容器序列化)
我们书写testjson.cpp
强大到直接把C++ STL中的容器内容可以直接序列化成Json字符串

#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
string func1()
{
    json js;//定义一个json类型的对象//添加数组
    js["msg_type"] = 2;
    js["from"] = "linzeyu";
    js["to"] = "zhang san";
    js["msg"] = "hello, are you ok now?";
 
    string sendBuf = js.dump();//输出的意思 
    //cout<<sendBuf.c_str()<<endl;//转成char*
    return sendBuf;
}

//json序列化示例2
string 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;
    return js.dump();
}

//json序列化示例代码3
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<<js<<endl;
    //return sendBuf;
}
int main()
{
    //func1();
    //unc2();
    func3();
    return 0;
}

运行
在这里插入图片描述

我们可以把json转成字符串发送给网络

#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
string func1()
{
    json js;//定义一个json类型的对象//添加数组
    js["msg_type"] = 2;
    js["from"] = "linzeyu";
    js["to"] = "zhang san";
    js["msg"] = "hello, are you ok now?";
 
    string sendBuf = js.dump();//输出的意思 
    //cout<<sendBuf.c_str()<<endl;//转成char*
    return sendBuf;
}

//json序列化示例2
string 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;
    return js.dump();
}

//json序列化示例代码3
string 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;
}

int main()
{
    //func1();
    //unc2();
    func3();
    return 0;
}

Json数据反序列化

当从网络接收到字符串为Json格式,可以用JSON for Modern C++ 直接反序列化取得数据或者直接反序列化出对象,甚至容器,强大无比!

int main()
{
    string recvBuf = func1();
    //数据的反序列化   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;
}

运行
在这里插入图片描述
其他函数的反序列如实现包含在如下,我汇总了

testjson.cpp

#include "json.hpp"
using json = nlohmann::json;

#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;

//json序列化示例1
string func1()
{
    json js;//定义一个json类型的对象//添加数组
    js["msg_type"] = 2;
    js["from"] = "linzeyu";
    js["to"] = "zhang san";
    js["msg"] = "hello, are you ok now?";
 
    string sendBuf = js.dump();//输出的意思 
    //cout<<sendBuf.c_str()<<endl;//转成char*
    return sendBuf;
}

//json序列化示例2
string 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;
    return js.dump();
}

//json序列化示例代码3
string 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;
}

int main()
{
    //func1();
    //unc2();
    //func3();
    string recvBuf = func1();
    //string recvBuf = func2();
    //string recvBuf = func3();
    
    //数据的反序列化   json字符串 =》反序列化 数据对象(看作容器,方便访问)
    json jsbuf = json::parse(recvBuf);
    
    cout<<jsbuf["msg_type"]<<endl;
    cout<<jsbuf["from"]<<endl;
    cout<<jsbuf["to"]<<endl;
    cout<<jsbuf["msg"]<<endl;

    //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;

    //vector<int> vec = jsbuf["list"]; //js对象里面的数组类型,直接放入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;
    //}
    //cout << endl;

    return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值