Json-Rpc框架(JsonCpp库使用介绍)

阅读导航

  • 引言
  • 一、Json数据格式
  • 二、JsonCpp介绍
  • 三、JsonCpp使用示例
  • 四、封装Json工具类

引言

JsonCpp,作为一个广受欢迎的C++ JSON库,以其易用性、高性能和丰富的功能集赢得了众多开发者的青睐。它不仅提供了简洁直观的API用于JSON数据的解析和生成,还通过良好的异常处理机制和类型安全的设计,确保了代码的稳定性和可维护性。在接下来的内容中,我们将详细介绍JsonCpp的基本用法、核心特性以及它是如何与我们的Json-Rpc框架无缝集成的,从而帮助我们更加高效地处理JSON数据,推动项目向前发展。

一、Json数据格式

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易于人阅读和编写的文本格式来存储和表示结构化数据,且这种格式独立于任何编程语言。

🎯例如:我们想表示⼀个同学的学⽣信息

  • 💻C++代码表示
char *name = "xx";
int age = 18;
float score[3] = {88.5, 99, 58};
  • 💻Json 表⽰
{"姓名" : "xx","年龄" : 18,"成绩" : [88.5, 99, 58],"爱好" : {"书籍" : "西游记","运动" : "打篮球"}
}

JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但JSON是独立于语言的,并且被许多现代编程语言所支持。JSON的主要数据类型包括:

  1. 对象:对象在JSON中以花括号{}包围,它们由键值对组成,键和值之间通过冒号:分隔,每对键值对之间使用逗号,分隔。键必须是字符串,而值可以是字符串、数字、布尔值、数组、对象或null。

  2. 数组:数组在JSON中以中括号[]包围,它们包含了一系列的值,这些值可以是字符串、数字、布尔值、数组、对象或null。数组中的值通过逗号,分隔。

  3. 字符串:字符串在JSON中必须使用双引号""包围,不能使用单引号。字符串中可以包含转义字符,例如\n表示换行,\"表示双引号本身等。

  4. 数字:JSON中的数字可以是整数或浮点数,不需要额外的引号或格式标记。数字可以非常大或非常精确,且遵循IEEE 754标准。

  5. 布尔值:布尔值在JSON中表示为truefalse,它们不区分大小写,但习惯上写作小写形式。

二、JsonCpp介绍

Jsoncpp 库是一个专注于处理JSON格式数据的C++库,它提供了两个核心功能:序列化和反序列化

序列化功能允许开发者将C++中的数据结构(如对象、数组等)转换成JSON格式的字符串,这种字符串形式便于数据的存储、传输或网络交换。

反序列化功能则是这一过程的逆操作,它能够将JSON格式的字符串解析回C++中的数据结构,使得程序能够方便地读取和处理这些数据。

Json 数据对象类的表⽰

class Json::Value {  
public:  // 赋值操作符重载  Value& operator=(const Value& other);  // 通过字符串键访问成员,支持赋值和获取  Value& operator[](const std::string& key);  Value& operator[](const char* key);  // 移除具有指定键的成员  Value removeMember(const char* key);  // 通过索引访问数组元素(只读)  const Value& operator[](ArrayIndex index) const;  // 向数组末尾添加元素  Value& append(const Value& value);  // 获取数组元素的数量  ArrayIndex size() const;  // 类型转换函数  std::string asString() const;   // 转换为std::string  const char* asCString() const;  // 转换为const char*  int asInt() const;              // 转换为int  float asFloat() const;          // 转换为float  bool asBool() const;            // 转换为bool  
};

📌Jsoncpp 库主要借助三个类以及其对应的少量成员函数完成序列化及反序列化

  • 序列化接口
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;
}
  • 反序列化接口
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;
}

三、JsonCpp使用示例

#include <iostream>  
#include <sstream>  
#include <string>  
#include <memory>  
#include <jsoncpp/json/json.h>  // 实现数据的序列化,将Json::Value对象转换为JSON格式的字符串  
bool serialize(const Json::Value &val, std::string &body) {  std::stringstream ss; // 创建一个字符串流,用于存储序列化后的JSON字符串  // 先实例化一个StreamWriterBuilder对象,它是用于创建StreamWriter对象的工厂  Json::StreamWriterBuilder swb;  // 通过StreamWriterBuilder对象来生成一个StreamWriter对象的智能指针  std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());  // 调用StreamWriter对象的write方法,将Json::Value对象序列化到字符串流中  int ret = sw->write(val, &ss);  if (ret != 0) { // 如果序列化失败(通常ret应为0表示成功)  std::cout << "json serialize failed!\n";  return false;  }  body = ss.str(); // 将字符串流中的内容赋值给body  return true;  
}  // 实现json字符串的反序列化,将JSON格式的字符串解析为Json::Value对象  
bool unserialize(const std::string &body, Json::Value &val) {  // 实例化CharReaderBuilder对象,它是用于创建CharReader对象的工厂  Json::CharReaderBuilder crb;  // 通过CharReaderBuilder对象生成一个CharReader对象的智能指针  std::string errs; // 用于存储解析过程中可能出现的错误信息  std::unique_ptr<Json::CharReader> cr(crb.newCharReader());  // 调用CharReader对象的parse方法,将JSON字符串解析为Json::Value对象  // 注意:parse方法的第二个参数是字符串的结束位置(指向字符串末尾的下一个位置)  bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);  if (ret == false) { // 如果解析失败  std::cout << "json unserialize failed : " << errs << std::endl;  return false;  }  return true;  
}  int main()  
{  // 初始化一些示例数据  const char *name = "小明";  int age = 18;   const char *sex = "男";  float score[3] = {88, 77.5, 66};  // 创建一个Json::Value对象来存储学生信息  Json::Value student;  student["姓名"] = name; // 添加姓名  student["年龄"] = age;  // 添加年龄  student["性别"] = sex;  // 添加性别  // 添加成绩,需要逐个添加,因为score是一个数组,而Json::Value需要逐个元素处理  for (int i = 0; i < 3; ++i) {  student["成绩"].append(score[i]);  }  // 添加爱好,爱好也是一个Json::Value对象,包含书籍和运动两个字段  Json::Value fav;  fav["书籍"] = "西游记";  fav["运动"] = "打篮球";  student["爱好"] = fav; // 将爱好对象添加到学生信息中  std::string body;  // 序列化学生信息到字符串body中  serialize(student, body);  std::cout << body << std::endl; // 打印序列化后的JSON字符串  // 示例:反序列化一个JSON字符串  std::string str = R"({"姓名":"小黑", "年龄": 19, "成绩":[32, 45, 56]})";  Json::Value stu;  bool ret = unserialize(str, stu);  if (ret == false)   return -1; // 如果反序列化失败,则退出程序  // 访问并打印反序列化后的JSON对象中的信息  std::cout << "姓名: " << stu["姓名"].asString() << std::endl;  std::cout << "年龄: " << stu["年龄"].asInt() << std::endl;  int sz = stu["成绩"].size();  for (int i = 0; i < sz; i++) {  std::cout << "成绩: " << stu["成绩"][i].asFloat() << std::endl;  }  return 0;  
}

编译运⾏程序查看序列化和反序列化结果

{"姓名":"小明","年龄":18,"性别":"男","成绩":[88.0,77.5,66.0],"爱好":{"书籍":"西游记","运动":"打篮球"}
}  姓名: 小黑  
年龄: 19  
成绩: 32  
成绩: 45  
成绩: 56

四、封装Json工具类

#include <iostream>  
#include <sstream>  
#include <string>  
#include <memory>  
#include <jsoncpp/json/json.h>  class json_util  
{  
public:  // 序列化: Json对象 -> 字符串  // 输入输出型参数  // root输入参数:表示要序列化的json对象  // str输出参数: 表示序列化之后的字符串  static bool serialize(const Json::Value &root, std::string &str)  {  Json::StreamWriterBuilder swb;  std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());  std::stringstream ss;  int ret = sw->write(root, &ss);  if (ret != 0) {  std::cout << "Serialize failed!" << std::endl;  return false;  }  str = ss.str();  return true;  }  // 反序列化: 字符串 -> Json对象  // 输入输出型参数  // str输入参数: 表示需要反序列化的字符串  // root输出参数:表示反序列化后的json对象  static bool unserialize(const std::string &str, Json::Value &root)  {  Json::CharReaderBuilder crb;  std::unique_ptr<Json::CharReader> cr(crb.newCharReader());  std::string errs; bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &root, &errs);  if (!ret) {  std::cout << "UnSerialize failed! Errors: " << (errs.empty() ? "None" : errs) << std::endl;  return false;  }  return true;  }  
};  

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言语句、语句分类及注释

文章目录 一、语句和语句分类二、注释&#x1f355;注释是什么&#xff1f;为什么写注释&#xff1f;1. /**/的形式2. //的形式3. 注释会被替换 三、随机数的生成1.rand函数2.srand函数3.time函数4.设置随机数的范围 四、C99中的变长数组五、问题表达式解析表达式1表达式2表达式…

redis中的数据类型(Set与ZSet)

&#xff08;一&#xff09;set set在我们目前有两个意思&#xff0c;首先就是这里使用的集合&#xff0c;第二个是我们的set和get方法 因为set是一个集合&#xff0c;所以他具有集合的一些特点&#xff1a; 1.集合中的元素无序 2.集合中的元素是不可重复的 3.集合间是可…

2.点位管理开发(续)及设计思路——帝可得后台管理系统

目录 前言一、页面原型二、修改1、页面展示2、新增 3 、总结思路 前言 提示&#xff1a;本篇继续点位管理的改造 一、页面原型 页面展示新增 二、修改 1、页面展示 页面修改&#xff1a;修改标签换行、顺序顺序、地址过长时换行问题&#xff1b; <el-table v-loading…

大厂笔试现已经禁用本地IDE怎么看

如果我说本来面试做题这种事情就是反人类你相信吗&#xff1f; 这个罪恶的源头就是 Google&#xff0c;说是为了选择高素质的计算机编程水平的人才&#xff0c;然后把面试就变成了考试&#xff0c;最大的受益者当然是印度人了。 当把一个考察过程变成标准化的考试过程&#x…

前后端传输文件(图片)

前端&#xff1a;Vue | 后端&#xff1a;.NET&#xff08;ASP.NET Core&#xff09; 情况1&#xff1a;前端>后端 前端&#xff1a; 1.设置 header 为 multipart/form-data 2.将数据封装为 FormData 类型 const formData new FormData() ......获取数据并通过append函数…

PHP__sleep和__wakeup有什么区别

在PHP中&#xff0c;__sleep 和 __wakeup 是两个魔术方法&#xff08;Magic Methods&#xff09;&#xff0c;它们与对象的序列化和反序列化过程紧密相关。这两个方法允许开发者在对象被序列化&#xff08;存储或传输&#xff09;和反序列化&#xff08;恢复&#xff09;时执行…

电脑失声,一招搞定

早已习惯了Edge浏览器的“大声朗读”功能&#xff0c;今天值班&#xff0c;值班室用的两台电脑只配有耳机&#xff0c;没有音箱&#xff0c;顿时感觉不适。 先找了一个带功放的老音箱&#xff0c;发现少了电箱到功放的音频线。 一顿搜索&#xff0c;在找到音频线的同时&#…

【案例】平面云

教程案例视频&#xff1a;Unity Shader Graph - 云教程 开发平台&#xff1a;Unity 2022 开发工具&#xff1a;Unity ShaderGraph   一、效果展示 二、ShaderGraph 路线图 三、案例分析 核心思路&#xff1a;使用 Noise&#xff08;噪声&#xff09;模拟云层状态   3.1 说明…

Chat登录时出现SSO信息出错的解决方法

目录 1. 问题所示2. 问题所示3. 解决方法 1. 问题所示 此贴主要是总结回顾&#xff0c;对此放置在运维专栏 出现如下问题&#xff0c;很懵&#xff0c;以为是节点挂了还是网址蹦了 一直刷新&#xff0c;登录之后就出现这个问题 2. 问题所示 对于SSO&#xff0c;也就是单点登…

负载均衡--相关面试题(六)

在负载均衡的面试中&#xff0c;可能会遇到一系列涉及概念、原理、实践应用以及技术细节的问题。以下是一些常见的负载均衡面试题及其详细解答&#xff1a; 一、什么是负载均衡&#xff1f; 回答&#xff1a;负载均衡是一种将网络请求或数据传输工作分配给多个服务器或网络资源…

详解JavaScript函数属性、方法和构造函数

函数属性、方法和构造函数 JS中&#xff0c;函数是值&#xff0c;对函数执行typeof运算会返回function&#xff0c;但是函数是JS中特殊的对象&#xff0c;也可以拥有属性和方法。 length属性 函数体里面&#xff0c;arguments.length表示传入函数的实参个数&#xff0c;而函…

2024年优化苹果免签封装APP H5站打包苹果APP 绿标-永不掉千(永久使用)

大家都知道苹果手机做APP签名很贵&#xff0c; 这个程序就是吧您的H5网站 一切网页可以打开的&#xff0c;封装成app 苹果手机上可以直接安装使用 永久可用&#xff01;&#xff01;很简单&#xff0c;可以看视频教程来安装使用&#xff0c; 视频教程&#xff1a; https://ww…

修改Anaconda虚拟环境默认安装路径(Linux系统)

文章目录 修改Anaconda虚拟环境默认安装路径(Linux系统)1.方法一&#xff1a;使用--prefix参数2.方法二&#xff1a;配置conda环境的默认安装位置 修改Anaconda虚拟环境默认安装路径(Linux系统) 1.方法一&#xff1a;使用--prefix参数 在创建虚拟环境时&#xff0c;使用--pre…

macOS编译和运行prometheus2.54

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文详述了在macOS(M2芯片)上编译和运行prometheus2.54版本的过程&#xff0c;以及安装node_exporter和grafana并使用prometheus指标进行展示 本地…

wzoissb的博客网(感谢CSDN支持)

感谢CSDN提供技术支持&#xff01;&#xff01;&#xff01; wzoissb的博客网站&#xff01;&#xff01;&#xff01;今天发布&#xff01;&#xff01;&#xff01; 我的主页 wzoi账号不公布 LUOGU 账号 其余网络账号…

vue3导入本地图片2种实现方法

在<script setup>中使用import语法&#xff1a; <template><img :src"logo" alt"Logo"> </template><script setup> import logo from ./assets/logo.png; </script> 使用Vue的ref来动态地在<script setup>中…

openpnp - 底部相机高级校正的参数设置

文章目录 openpnp - 底部相机高级校正的参数设置概述笔记修改 “Radial Lines Per Calibration Z” 的方法不同 “Radial Lines Per Calibration Z”的校验结果不同 “Radial Lines Per Calibration Z”的设备校验动作的比较总结备注END openpnp - 底部相机高级校正的参数设置 …

根据给定的相机和镜头参数,估算相机的内参。

1. 相机分辨率和传感器尺寸 最高分辨率&#xff1a;6000 4000 像素传感器尺寸&#xff1a;22.3 mm 14.9 mm 2. 计算像素大小 需要计算每个像素对应的实际尺寸&#xff08;mm/pixel&#xff09;&#xff1a; 水平方向像素大小&#xff1a; 垂直方向像素大小&#xff1a; …

JAVA实现大写金额转小写金额

在金融行业中经常需要把大写金额转成小写金额&#xff0c;之前在一次开发中有个类似的需求&#xff0c;翻阅了好多博文&#xff0c;都没找到合适的&#xff0c;故没办法&#xff0c;就花了点时间研究并实现! 实现代码如下: private static final Character ZERO 零;private s…

国外电商系统开发-运维系统批量添加服务器

您可以把您准备的txt文件&#xff0c;安装要求的格式&#xff0c;复制粘贴到里面就可以了。注意格式&#xff01; 如果是“#” 开头的&#xff0c;则表示注释&#xff01;