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
相关推荐
He BianGu2 小时前
【笔记】介绍 WPF XAML 中 Binding 的 StringFormat详细功能
笔记·wpf
Rousson2 小时前
硬件学习笔记--78 MCU复位电路简介
笔记·学习
追逐梦想的小孩2 小时前
从零开始学华为:Console口连接设备
网络·华为·交换机
Boilermaker19922 小时前
【Java】网络编程(5)
网络
~无忧花开~3 小时前
JavaScript学习笔记(十七):ES6生成器函数详解
开发语言·前端·javascript·笔记·学习·es6·js
optimistic_chen4 小时前
【Java EE进阶 --- SpringBoot】Mybatis操作数据库(基础)
数据库·经验分享·spring boot·笔记·spring·java-ee·mybatis
lpfasd1234 小时前
SSL证书有效期缩短至200天的影响
网络·网络协议·ssl
艾菜籽5 小时前
网络原理-HTTP
网络·网络协议·http
ASKED_20195 小时前
ChatGPT From Zero To Hero - LLM学习笔记(一)
笔记·学习·chatgpt
GoldenaArcher5 小时前
Postman 学习笔记 III:CLI 自动化测试与 Jenkins CI/CD 实践
笔记·学习·postman