Linux系统C++开发工具(四)—— jsoncpp 使用指南

文章目录

概念简述

JSON 的全称是 JavaScript Object Notation。

  • 核心定义:它是一种轻量级的数据交换格式,用来做序列化与反序列化

Json格式可辅助解决 TCP 传输中的粘包问题,粘包------发送方连续发送多个独立数据包,接收方可能一次性读取到合并数据。比如发送6和7,接收到67。

对于粘包问题,可以在数据之间添加一些标识符来区分它们,比如": ",当接收到完整的数据包后根据这些标识符就可以区分出它们。这个操作就是序列化和反序列化。

数据包以什么格式传递是通信双方(服务器和客户端)约定好的,即协议。序列化和反序列化就是协议的一部分。

例如Json会以这样的格式记录一个学生信息:

复制代码
{
		"姓名": "张三",
		"年龄": 18,
		"成绩": [88.8,89,69.5]
}

一个花括号{}就是一个对象,方括号[ ]就是数组,对象之间可以嵌套,如一个班级的信息:

复制代码
[{},{},{}]

Json的安装:

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

数据存取

Json::Value类

这个类用于进行数据中间存储。将多个字段数据进行序列化,需要将数据存储到Value对象中,若要将一个json格式的字符串反序列化,需要用该类对象来接收结果。
数据的存储

Json::Value类里面重载了=运算符和[]运算符,可以如下方式进行数据存储:

json 复制代码
Json::Value val;
val["姓名"]="张三";
val["年龄"]=18;
val["成绩"].append(88); //如果要存储一个数组需要用append接口
val["成绩"].append(95.5); //再次调用来新增第二个元素
......

数据的访问

数据访问时同样用方括号[ ]运算符进行访问。在访问时用的类型有多中多样,通过接口调用来转化,如下:

json 复制代码
val["姓名"].asString();
val["年龄"].asInt();
val["成绩"][0].asFloat();
val["成绩"][1].asFloat();
......
//对于数组的数据也可提供size()获取元素个数,然后进行遍历。

序列化

StreamWriter类

该类提供了write()接口,用来做序列化

int write(Value const& root, std::ostream* sout)

  • root:一个Json::Value对象,即需要序列化的数据
  • sour:该参数用来接收序列化的结果,通常传入std::stringstream类型
  • 注意:StreamWriter类不能自己构造,需要使用StreamWriterBulider工厂类对象构造。通过工厂类对象里面的newStreamWriter接口生成StreamWriter对象。

反序列化

CharReader类

该类提供parse()接口,用来做反序列化

bool parse(char const* beginDoc, char const* endDoc, Value* root, std::string* errs)

  • beginDoc:JSON 字符串的起始指针
  • endDoc:JSON 字符串的结束指针
  • root:输出型参数,解析后的 JSON 对象
  • errs:输出型参数,错误信息

CharReader类也不能自己构造,需要使用CharReaderBuilder工厂类对象构造,通过工厂类里面的newCharReader接口生成CharReader类。

示例

main.cc文件

cpp 复制代码
#include <json/json.h>
#include <iostream>
#include <sstream>
bool Serialize(const Json::Value& val,std::string& out)
{
    //通过工厂类构建StreamWriter
    auto nsw = Json::StreamWriterBuilder().newStreamWriter();//因为工厂类在该场景中不在使用,所以构造临时对象。
    std::stringstream ss;
    int ret = nsw->write(val,&ss);
    if(ret != 0)
    {
        std::cout<<"序列化失败";
        return false;
    }
    out = ss.str();
    return true;
}
bool UnSerialize(const std::string& str,Json::Value& val)
{
    auto crb = Json::CharReaderBuilder().newCharReader();
    std::string erro;
    bool ret = crb->parse(str.c_str(),str.c_str()+str.size(),&val,&erro);
    if(ret == false)
    {
        std::cout<<"反序列化失败"<<std::endl;
        return false;
    }
    return true;
}
int main()
{
    //构建数据
    Json::Value val;
    val["姓名"] = "张三";
    val["年龄"] = 18;
    val["成绩"].append(90);
    val["成绩"].append(90.5);
    val["成绩"].append(89.5);
    
    //序列化
    std::string out;
    Serialize(val,out);
    std::cout<<out<<std::endl;
    
    //反序列化
    Json::Value root;
    UnSerialize(out,root);
    std::cout<<root["姓名"].asString()<<std::endl;
    std::cout<<root["年龄"].asInt()<<std::endl;
    for(int i=0;i<root["成绩"].size();i++)
    {
        std::cout<<root["成绩"][i]<<" ";
    }
    std::cout<<std::endl;
    return 0;
}

makefile文件

makefile 复制代码
test:main.cc
	g++ $^ -o $@ -std=c++17 -ljsoncpp

执行结果:

提示:显示的乱码是数据在转化为Json串后对中文进行了转义存储。

非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!

相关推荐
小辰记事本1 小时前
从零读懂RoCEv2数据包构造:从WQE到线缆上的完整旅程
服务器·网络·网络协议·rdma
杜子不疼.2 小时前
【C++ AI 大模型接入 SDK】 - DeepSeek 模型接入(上)
开发语言·c++·chatgpt
小鹏linux2 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
北京耐用通信2 小时前
全域适配工业场景耐达讯自动化Modbus TCP 转 PROFIBUS 网关轻松实现以太网与现场总线互通
网络·人工智能·网络协议·自动化·信息与通信
在角落发呆3 小时前
Linux转发配置:解锁网络互联的核心密码
linux·运维·网络
石山代码3 小时前
C++ 内存分区 堆区
java·开发语言·c++
齐潇宇3 小时前
Zabbix 7 概述与配置
linux·zabbix·监控告警
江公望5 小时前
Ubuntu htop命令,10分钟讲清楚
linux·服务器
哎呦,帅小伙哦5 小时前
Linux 时间:从原子钟到 clock_gettime 的每一面
linux·运维·服务器
张小姐的猫5 小时前
【Linux】多线程 —— 线程互斥
linux·运维·服务器·c++