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
相关推荐
草莓熊Lotso5 小时前
【C++】递归与迭代:两种编程范式的对比与实践
c语言·开发语言·c++·经验分享·笔记·其他
我爱挣钱我也要早睡!7 小时前
Java 复习笔记
java·开发语言·笔记
江团1io09 小时前
深入解析TCP核心机制:连接管理、流量与拥塞控制
服务器·网络·tcp/ip
汇能感知12 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun12 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao13 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
海拥✘13 小时前
深入理解 IP 地址:概念、分类与日常应用
网络·网络协议·tcp/ip
是誰萆微了承諾13 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT14 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习