JsonCpp库的使用

目录

一、Json数据格式

二、JsonCpp介绍

2.1 Json::Value

2.2 序列化接口

2.3 反序列化接口

三、JsonCpp的使用

3.1 头文件包含

3.2 序列化

3.3 反序列化

四、补充


Json 是⼀种数据交换格式,它采⽤完全独⽴于编程语⾔的⽂本格式来存储和表示数据。

一、Json数据格式

Json 的数据类型包括对象,数组,字符串,数字等。
• 对象:使⽤花括号 { } 括起来的表⽰⼀个对象
• 数组:使⽤中括号 [ ] 括起来的表⽰⼀个数组
• 字符串:使⽤常规双引号 " " 括起来的表示⼀个字符串
• 数字:包括整形和浮点型,直接使用

C语言 代码表示:

char *name = "张三";
int age = 18;
int score[3] = { 100, 110, 96 };

Json 表示:

{"姓名" : "张三","年龄" : 18,"成绩" : [100, 110, 96],"喜欢的人" :{"姓名" : "小丽","年龄" : "18","成绩" : [ 110, 112, 110]}
}

注意,在Json中,每个对象的各个数据用 , 分割,最后一行数据不需要使用 ,  

二、JsonCpp介绍

上述 Json 只是为我们提供了一种格式,具体的实现还需要每种语言配有对应的框架,这里我们就开始认识一下 JsonCpp ,主要学习其中的三个类即可。

2.1 Json::Value

如果要将数据对象进行序列化,就需要先将对象存储到 Json::Value 对象中
如果要将数据传输后进行反序列化,即解析,会将数据对象放入到 Json::Value 对象中

class Json::Value
{Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过 = Value& operator[](const std::string& key); //简单的⽅式完成 val["name"] = "xx";Value& operator[](const char* key);Value removeMember(const char* key); //移除元素const Value& operator[](ArrayIndex index) const; //val["score"][0]Value& append(const Value& value); //添加数组元素val["score"].append(88);ArrayIndex size() const; //获取数组元素个数 val["score"].size();std::string asString() const; //转string string name = val["name"].asString();const char* asCString() const; //转char* char *name = val["name"].asCString();Int asInt() const; //转int int age = val["age"].asInt();float asFloat() const; //转float float weight = val["weight"].asFloat();bool asBool() const; //转 bool bool ok = val["ok"].asBool();
};

下面简单认识一下其中的部分成员:

= 运算符重载:Value 重载了[]和=,因此所有的赋值和获取数据都可以通过 = 来赋值

[] 运算符重载:Value 重载了[]和=,因此所有的赋值和获取数据都可以通过 = 来赋值

例:val ["name"] = "张三"

[] 运算符重载:使 Value 中的数组成员可以直接使用下标访问

例: val["score"][0]

append 函数:直接追追加 Value 中的数组成员

例: val["score"].append(89) 如果不使用append,89会覆盖上一个score成员!

size 函数:返回 Value 中的数组成员的数量,方便遍历某成员

2.2 序列化接口

class JSON_API StreamWriter 
{virtual int write(Value const& root, std::ostream* sout) = 0;
}
class JSON_API StreamWriterBuilder : public StreamWriter::Factory 
{virtual StreamWriter* newStreamWriter() const;
}

重点是 StreamWriter::write() 作为序列化函数,

其中,Json::StreamWriterBuilder 是继承自 Json::StreamWriter 的工厂类,用于生产 Json::StreamWriter 对象

write 写入成功时,会返回一个0,不成功则会返回非0

第一个参数指的是要进行序列化的 Json::Value 对象

第二个参数指的是要写入的输出流

2.3 反序列化接口

class JSON_API CharReader 
{virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, std::string* errs) = 0;
}
class JSON_API CharReaderBuilder : public CharReader::Factory 
{virtual CharReader* newCharReader() const;
}

重点是 Json::CharReader::parse() 作为反序列化函数,

其中,Json::CharReaderBuilder 是继承自 Json::CharReader 的工厂类,用于生产 Json::CharReader 对象

parse 返回值是布尔类型,若 parse 成功返回 true,反之返回 true

第一个参数是要反序列化数据的起始地址

第二个参数是要反序列化数据的末尾地址

第三个参数是反序列化后数据要写入的 Json::Value 对象,要进行地址传参

第四个参数是报错信息,可以定义一个 std::string 对象进行地址传参

三、JsonCpp的使用

3.1 头文件包含

如果你的环境中已经安装了 Json 库,那么我们只需要 jsoncpp/json/json.h 文件,所以头文件如下

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

此外,如果使用 makefile ,还需要连接上 jsoncpp ,这里我将序列化和反序列化的 demo 分成了两个文件,如下:

all:Serialize unSerialize
Serialize:Serialize.cppg++ -o $@ $^ -std=c++11 -ljsoncpp
unSerialize:unSerialize.cppg++ -o $@ $^ -std=c++11 -ljsoncpp
.PHONY:clean
clean:rm -rf unSerialize Serialize

3.2 序列化

可以先定义变量存储我们需要传入 Json::Value 的值,然后直接定义一个 Json::Value 的对象,并为对象赋值。

随后需要序列化时不能直接使用 Json::StreamWriter ,而是要先定义一个 Json::StreamWriterBuilder 对象,再创建一个 Json::StreamWriter 对象的指针接收由 Json::StreamWriterBuilder 对象调用其 newStreamWriter() 的返回值。

最后,可以使用 writer 函数,并指定输出流对象。

//数据序列化
void Serialize()
{const char* name = "XiaoMing";const char*sex = "Man";int age = 18;int score[3] = { 100, 110, 96 };Json::Value student;student["Name"] = name;student["Sex"] = sex;student["Age"] = age;student["Score"].append(score[0]);student["Score"].append(score[1]);student["Score"].append(score[2]);//定义工厂类对象Json::StreamWriterBuilder swb;Json::StreamWriter *sw(swb.newStreamWriter());sw->write(student, &std::cout);std::cout << std::endl;delete sw;
}int main()
{Serialize();return 0;
}

同时,还需要释放 Json::StreamWriter 对象的内存,以后会进行进一步优化。 

为了避免内存泄露,可以使用智能指针管理 Json::StreamWriter 对象,同时,为了代码更加简洁,可以对 Serialize() 进一步封装。将要序列化的信息作为传入参数,并使用输出型参数以字符串的方式输出序列化后的信息中,这里要使用到 stringstream 用作数据的缓冲区,用于 Json::Value 格式转换到 std::string 格式。

将序列化后的信息带回到字符串后,可以打印出字符串的信息来查看序列化后的信息。

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>//数据序列化
bool Serialize(const Json::Value &val, std::string &body)
{//中间缓冲区,将 Json::Value 格式转换为 std::string 格式std::stringstream ss;//定义工厂类对象Json::StreamWriterBuilder swb;std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());//如果 write 返回值不为零,则错误int ret = sw->write(val, &ss);if (ret != 0){std::cout << "Serialize Error!";return false;}body = ss.str();return true;
}int main()
{const char* name = "XiaoMing";const char*sex = "Man";int age = 18;int score[3] = { 100, 110, 96 };Json::Value student;std::string body;student["Name"] = name;student["Sex"] = sex;student["Age"] = age;student["Score"].append(score[0]);student["Score"].append(score[1]);student["Score"].append(score[2]);Serialize(student, body);//打印字符串信息std::cout << body << std::endl;return 0;
}

可以看到序列化的结果是一样的。

3.3 反序列化

反序列化我们直接使用封装,先定义一个工厂类 Json::CharReaderBuilder,然后使用工厂类生成一个 Json::CharReader 对象,调用该对象的类内方法 parse 进行反序列化。

//数据反序列化
bool unSerialize(std::string &body, Json::Value &val)
{//定义工厂类Json::CharReaderBuilder crb;std::unique_ptr<Json::CharReader> cr(crb.newCharReader());//错误信息缓冲区std::string errs;bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);if (ret == false){std::cout << "unSerialize Error!";return false; }return true;
}

在进行测试时,可以直接自定义一个序列化字符串,在 R"()" 的小括号中定义出序列化的信息,然后使用 Json::Value 进行接收并分别打印:

int main()
{//序列化数据std::string s = R"({"Name":"XiaoHong", "Sex":"Woman", "Age":18})";//反序列化后的结果填入 Json::Value 中Json::Value stu;bool ret = unSerialize(s, stu);if (ret == false){return -1;}std::cout << "Name:" << stu["Name"].asString() << " Sex:" << stu["Sex"].asString() << " Age:" << stu["Age"].asString() << std::endl; return 0;
}

同时,在输出时,可以使用字符串 

四、补充

4.1 中文乱码

Json 也可以使用中文,如果你使用中文是乱码的话,如下:

那你可以在定义工厂类对象后添加以下信息:

// 设置 emitUTF8 使其输出原始的 UTF-8 编码而不是转义序列
swb["emitUTF8"] = true;

此时再重新编译,就可以得到不乱码的中文结果:

4.2 demo 源码

源码链接如下,有需要的可以参考 demo 源码:

从零实现JsonRpc框架: CPP项目——从零实现JsonRpc项目博客链接:https://blog.csdn.net/m0_75186846/category_12772639.html - Gitee.comicon-default.png?t=N7T8https://gitee.com/bright-and-sparkling-at-night/JsonRpc/tree/master/demo/jsoncpp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1522363.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Cvemap 到Nuclei模板映射

随着 ProjectDiscovery 的崛起&#xff0c;Nuclei、Katana、Subfinder、Naabu 以及最新添加的 cvemap 等工具纷纷出现&#xff0c;以增强勇敢者的武器库。 CVEmap 和 Nuclei 缺少功能 大多数渗透测试人员对缺少将cvemap结果直接“映射”到现有核心模板的功能感到失望。 这个绝…

macOS搭建Python3.11+Django4.2.15的平台框架使用Poetry管理

最近想使用Python开发&#xff0c;使用Django框架搭建平台&#xff0c;之前没有使用过Python&#xff0c;所以记录下整个过程&#xff1a; 1、Python版本的选择&#xff0c;直接去官网【Download Python | Python.org】看最新稳定版是哪个版本&#xff0c;选择安装&#xff0c…

Redis配置

redis配置管理 可以直接打开配置文件进行查看和修改&#xff0c;也可以通过config命令来进行查看和修改。 配置文件位置 Linux中默认在/etc/redis/redis.conf。Windows 中默认在安装目录下&#xff0c;名为 redis.windows.conf。 查看redis配置 使用redis-cli连接redis后&…

Anaconda安装并配置Python环境 | Python系列教程

Anaconda 是一个流行的 Python 数据科学和机器学习平台&#xff0c;它简化了包管理和部署的复杂性。Anaconda 旨在通过提供一个预配置的环境来加速数据分析、机器学习、科学计算和软件开发等领域的开发流程。总的来说&#xff0c;Anaconda 是一个强大的平台&#xff0c;它通过简…

ubunto中常见问题及WSL

ubunto中常见问题 ubuntu中vscode界面放大缩小的快捷方式ubuntu中vscode界面放大缩小的快捷方式_ubuntu中让vscode全屏-CSDN博客https://blog.csdn.net/weixin_47295886/article/details/123023748 解决出现无法使用sudo命令情况 解决出现无法使用sudo命令情况 - 知乎 (zhih…

DVP接口详解

背景知识 什么是DVP&#xff1f; DVP全称Digital Video Port&#xff08;数字视频端口&#xff09;是一种用于图像传感器和处理器之间传输视频数据的接口标准&#xff0c;DVP 接口采用并行传输方式&#xff0c;设计上属于低速总线&#xff0c;DVP没有特定的传输协议&#xff…

office365如何退回之前的版本

一夜之间&#xff0c;我的word使用起来感觉好麻烦。查询了一下&#xff0c;发现是word更新了。 感觉更新后一些功能很不好用&#xff0c;所以我决定返回之前使用的版本。现在记录一下这个过程&#xff0c;也可以供有需要的朋友参考。 打开cmd窗口&#xff0c;在第一行输入以下…

Vue3实时更新时间(年-月-日 时:分:秒)

代码案例 <script lang"ts" setup> import { ref,onMounted } from vue; const timer ref() const date ref("")//年月日 const moreTime ref("")//时分秒 onMounted(()>{//创建定时器1秒执行一次timer.value setInterval(() >…

真实:关于源代码防泄漏工作一些经验分享

互联网的飞速发展&#xff0c;各行各业都在往数字化转型&#xff0c;很多传统的业务数据都需要逐渐录入到电脑中&#xff0c;不仅节省了空间&#xff0c;还节约了成本。而这些数据都需要通过各类型的应用程序&#xff0c;进行分类&#xff0c;统计&#xff0c;展示&#xff0c;…

Apache DolphinScheduler项目与社区7-8月发展报告

各位热爱 Apache DolphinScheduler 的小伙伴们&#xff0c;社区7-8月报更新啦&#xff01;这里将记录 Apache DolphinScheduler 社区每月的重要更新&#xff0c;欢迎关注&#xff01; Merge Stars 感谢以下小伙伴上两个月为 Apache DolphinScheduler 项目和社区发展所做的精彩…

从K-Means到K-Medoid:聚类算法在缺陷报告分析中的性能比拼与优化探索

本文分享自华为云社区《聚类&#xff1a;k-Means 和 k-Medoid》作者&#xff1a; Uncle_Tom 1. 前言 在《对静态分析缺陷报告进行聚类&#xff0c;以降低维护成本》 提到使用 k-Medoid 通过相似缺陷的聚类&#xff0c;来减少程序员对大量缺陷分析的工作量。 k-Medoid 和传统的…

业务解耦-Spring事件监听的三种实现方式

实现ApplicationListener 步骤如下&#xff1a; 1.写Event类&#xff0c;需要继承Spring的ApplicationEvent类 2.写监听类&#xff0c;需要实现Spring的ApplicationListener接口&#xff0c;加上Component注解 3.监听类实现onApplicationEvent方法 4.通过ApplicationContext.p…

25届计算机毕业设计:如何用Java SpringBoot+Vue打造高效医疗器械管理系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

手游推广痛点解析,Xinstall如何助力厂商破解难题?

随着手游市场的日益繁荣&#xff0c;手游推广方式也在不断革新。从传统的地推、广告投放到如今新兴的CPA&#xff08;按动作付费&#xff09;和CPS&#xff08;按销售订单付费&#xff09;模式&#xff0c;手游推广正逐步走向效果导向的时代。而在这个过程中&#xff0c;Xinsta…

Ubuntu上安装剪切板管理软件

1. 更新系统和软件 确保你的系统和软件是最新的&#xff0c;有时更新可以修复这类错误。 sudo apt update sudo apt upgrade 2. 重新安装 Diodon 尝试卸载并重新安装 Diodon。 sudo apt remove diodon sudo apt install diodon 3. 检查依赖项 确保系统中安装了所有必要…

TPM管理咨询公司一走,企业又恢复原样,为什么?

在探讨“TPM管理咨询公司离开后&#xff0c;企业为何常常恢复原样”这一深刻问题时&#xff0c;我们不得不深入剖析TPM理念的本质、实施过程中的挑战以及企业在持续变革中面临的普遍困境。TPM作为一种以最大化设备综合效率为目标的生产维护体系&#xff0c;其核心理念在于通过全…

【数据结构】反射,枚举你必须知道的相关知识

前言&#xff1a; &#x1f31f;&#x1f31f;本期讲解关于反射以及枚举&#xff0c;希望能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;http://t.csdnimg.cn/7D225 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 目录 &#x1f…

linux固定ip

背景 VMware&#xff0c;centos7 查询 网关 linux指执行 ip addr 命令 拿到自动分配的ip : 192.168.150.102 [rootlocalhost ~]# cd /etc/sysconfig/network-scripts/ 执行: cd /etc/sysconfig/network-scripts/ 进入到network-scripts文件中 执行: vi ifcfg-ens33 编辑ifc…

猪八戒落地-第15届蓝桥省赛Scratch初级组真题第1题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第180讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

备战2024年全国大学生数学建模竞赛:湖羊养殖场空间利用率优化

目录 一、引言 二、问题分析 问题1&#xff1a;年化出栏量与羊栏缺口估算 问题2&#xff1a;最大化年化出栏量的生产计划 问题3&#xff1a;考虑不确定因素的生产计划 三、解题思路 1. 模型假设与变量设定 2. 问题1的建模与求解 3. 问题2的建模与优化 4. 问题3的建模与…