Linux笔记---协议定制与序列化/反序列化

1. 协议

我们在Linux笔记---计算机网络概述-CSDN博客中已经谈过协议的基本概念了,这里就不再复述。

放到程序员编程的角度来说,协议规定的就是如何在网络当中传输结构化的数据

显然,将结构化的数据直接以bit流的方式传输是不现实的,且不说各种语言对于同一种结构体的解释与编码是否相同,就是同种类型的变量是否兼容都是未知数。

我们不能指望与你通信的远端和你使用的是同一种语言。所以,我们需要将结构化的数据转换为可传输的格式,字符串就是我们的不二选择。

因为字符的编码是有独立的标准规定的,例如ASCII、base64。

协议就是用来规字符串与结构化数据之间如何相互转换的。遵守相同的协议,就是双方通信的前提。

2. 序列化与反序列化

  • 序列化:将结构化的数据转换字符串(如字节流、JSON、XML 等)的过程。
  • 反序列化:将序列化后的数据流恢复为内存中原始对象的过程,是序列化的逆操作。

3. JSONCPP库

我们可以自己约定如何进行序列化与反序列化,但是显然使用已有的开源库更加方便。

JSONCPP 是一款开源的 C++ 库 ,专门用于处理JSON(JavaScript Object Notation)数据格式,提供了 JSON 数据的解析、生成、修改和查询等核心功能。它具有跨平台、API 简洁、稳定性高的特点,广泛应用于 C++ 项目中(如接口数据交互、配置文件读写、日志格式化等场景)。

所谓JSON数据格式,就是上面的图中所显示的那样的字符串:用一个大括号将一个结构化的数据括起来,将其中的变量名和数值以字符串键值对的形式存储。

安装方式:

bash 复制代码
ubuntu:sudo apt-get install libjsoncpp-dev 
Centos: sudo yum install jsoncpp-devel

3.1 核心数据结构

JSONCPP 的核心设计围绕两个关键类展开,几乎所有操作都基于这两个类:

|--------------------|-----------------------------------------------------------------------|
| 类名 | 作用说明 |
| Json::Value | 表示一个 JSON 数据节点,可存储 JSON 支持的所有类型(对象、数组、字符串、数字、布尔、null),支持嵌套结构。 |
| Json::Document | 继承自 Json::Value,专门用于表示完整的 JSON 文档(根节点通常是对象或数组),提供解析字符串 / 文件的入口。 |

3.2 简单用法---序列化

首先,我们需要定义出一个Json::Value对象,使用map的同款写法可以定义键值对:

cpp 复制代码
#include <jsoncpp/json/json.h>

int main()
{
    Json::Value root;
    root["name"] = "张三";
    root["age"] = 18;
    root["gender"] = 'M';
}

接下来,要将root序列化可以有如下三种方式:

3.2.1 Json::Value 的 toStyledString

将 Json::Value 对象直接转换为格式化的 JSON 字符串,"Styled" 代表生成的JSON字符串会添加额外的空格与换行符来确保JSON串的可读性:

cpp 复制代码
#include <jsoncpp/json/json.h>
#include <iostream>

int main()
{
    Json::Value root;
    root["name"] = "张三";
    root["age"] = 18;
    root["gender"] = 'M';
    std::string json_str = root.toStyledString();
    std::cout << json_str << std::endl;
}

输出结果:
{
    "name" : "张三",
    "age" : "18",
    "gender" : "M"
}

这种风格的JSON串相对来说可读性较高。

3.2.2 Json::FastWriter 的 write

相对于 "Styled",FastWriter转换出的JSON串则不添加额外的空格和换行符:

cpp 复制代码
#include <jsoncpp/json/json.h>
#include <iostream>

int main()
{
    Json::Value root;
    root["name"] = "张三";
    root["age"] = 18;
    root["gender"] = 'M';
    Json::FastWriter writer;
    std::string json_str = writer.write(root);
    std::cout << json_str << std::endl;
}

输出结果:
{"name":"张三","age":"18","gender":"M"}

3.3 简单用法---反序列化

3.3.1 Json::Reader 的 parse

将JSON串反序列化为Json::Value对象:

cpp 复制代码
#include <jsoncpp/json/json.h>
#include <iostream>

int main()
{
    // JSON字符串
    std::string json_str = "{\"name\":\"张三\", \"age\":18, \"gender\":\"M\"}";
    
    Json::Reader reader; 
    Json::Value root;

    if(!reader.parse(json_str, root))
    {
        // 解析失败,输出错误信息 
        std::cout << "Failed to parse JSON: " << reader.getFormattedErrorMessages() << std::endl; 
        return 1;
    }

    // 访问Value对象的键值需要通过函数转化
    std::string name = root["name"].asString();
    int age = root["age"].asInt();
    char gender = root["gender"].asInt();
    
    std::cout << "name : " << name << endl;
    std::cout << "age : " << age << endl;
    std::cout << "gender : " << gender << endl;   
}

输出结果:
name : 张三
age : 18
gender : M
相关推荐
_OP_CHEN1 小时前
【Linux网络编程】(一)初识计算机网络:从独立主机到协议世界的入门之旅
linux·服务器·网络·网络协议·计算机网络·socket·c/c++
一袋米扛几楼985 小时前
【密码学】CrypTool2 工具是什么?
服务器·网络·密码学
码农的小菜园8 小时前
gradle常用指令使用笔记
笔记
南棱笑笑生9 小时前
20260310在瑞芯微原厂RK3576的Android14查看系统休眠时间
服务器·网络·数据库·rockchip
鸟电波9 小时前
硬件笔记——示波器篇
笔记
yy55279 小时前
LNAMP 网络架构与部署
网络·架构
Don.TIk9 小时前
SpringCloud学习笔记
笔记·学习·spring cloud
Godspeed Zhao10 小时前
现代智能汽车系统——CAN网络2
网络·汽车
cd118405110 小时前
AutoCAD Electrical 2020学习笔记
笔记·学习
爱丽_10 小时前
Docker 从原理到项目落地(镜像 / 容器 / 网络 / 卷 / Dockerfile)
网络·docker·容器