【C++集群聊天服务器(二)】|json简单入门

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) 的最佳实践

使用的时候,我们这样即可:

cpp 复制代码
#include "json.hpp" 
using json = nlohmann::json;

Json数据序列化

就是把我们想要打包的数据,或者对象,直接处理成Json字符串。简单理解,json字符串就是由大括号括起来的键值对。和我们C++里面的无序关联容器比较像,其实它底层就是使用链式哈希表进行存储。

案例一:Json完成字符串的序列化

cpp 复制代码
#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;
}

打印效果如下:

cpp 复制代码
{"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

cpp 复制代码
#include <string>
string sendBuf = js.dump();
cout << sendBuf.c_str << endl;

如果我们通过网络传输,肯定是吧 string 转换成 char*。

最后打印输出的结果和上面是一样的。

案例二:序列化

他可以序列化更加复杂的内容,

首先其中的key对应的 value 本身可以是普通的类型,也可以是字符串类型,甚至可以是数组类型。

cpp 复制代码
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;
}

如何理解:

cpp 复制代码
    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:

cpp 复制代码
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;
}

打印结果如下:

cpp 复制代码
{"list":[1,2,5],"path":[[1,"挺好的?"],[2,"华山"],[3,"泰山"]]}

这个序列化结果显示,Json吧 vector 直接序列化成了数组,把 map 序列化成了"数组里面套数组"。

现在我们把它进行序列化:

cpp 复制代码
string sendBuf = js.dump(); //json数据对象=》序列化 json字符串
cout << sendBuf.c_str() << endl;

这样我们可以把它通过网络发送

相关推荐
yuyanjingtao13 分钟前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
Youkiup25 分钟前
【linux 常用命令】
linux·运维·服务器
闻缺陷则喜何志丹29 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
qq_2975046129 分钟前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
charlie11451419140 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
weixin_4373982142 分钟前
Linux扩展——shell编程
linux·运维·服务器·bash
小林熬夜学编程1 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
倔强的石头1061 小时前
【C++指南】类和对象(九):内部类
开发语言·c++
冷心笑看丽美人1 小时前
探秘 DNS 服务器:揭开域名解析的神秘面纱
linux·运维·服务器·dns
wenxiaocsdn1 小时前
某科技局国产服务器PVE虚拟化技术文档
运维·服务器