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

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

相关推荐
moringlightyn10 小时前
c++11可变模版参数 emplace接口 新的类功能 lambda 包装器
开发语言·c++·笔记·其他·c++11·lambda·包装器
郝学胜-神的一滴10 小时前
使用Linux系统函数递归遍历指定目录
linux·运维·服务器·开发语言·c++·软件工程
pusue_the_sun10 小时前
操作系统:进程的短程调度
运维·服务器
会开花的二叉树11 小时前
C++微服务 UserServer 设计与实现
开发语言·c++·微服务
我星期八休息11 小时前
C++智能指针全面解析:原理、使用场景与最佳实践
java·大数据·开发语言·jvm·c++·人工智能·python
·白小白11 小时前
力扣(LeetCode) ——11.盛水最多的容器(C++)
c++·算法·leetcode
软件技术员11 小时前
使用ACME自动签发SSL 证书
服务器·网络协议·ssl
Murphy_lx12 小时前
Linux系统--信号(4--信号捕捉、信号递达)陌生概念篇
linux·运维·服务器
Asuncion00712 小时前
Docker核心揭秘:轻量级虚拟化的革命
服务器·开发语言·docker·云原生
焱焱枫12 小时前
Linux疑难杂症诊断利器:深入解析 fuser 命令
linux·运维·服务器