【从零实现JsonRpc框架#1】Json库介绍

1.JsonCpp第三方库

JSONCPP 是一个开源的 C++ 库,用于解析和生成 JSON(JavaScript Object Notation)数据。它提供了简单易用的接口,支持 JSON 的序列化和反序列化操作,适用于处理配置文件、网络通信数据等场景。

2.Json 数据格式

JSON 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。

比如:我们想表示一个 同学的信息

C 代码表示:

char *name = "xx";
int age = 18;
float score[3] = {88.5, 99, 58};

Json 表示:

{"姓名" : "xx","年龄" : 18,"成绩" : [88.5, 99, 58],"爱好" :{"书籍" : "西游记","运动" : "打篮球"}
}

包含以下基本类型:

  • 对象(Object):键值对集合,用 {} 包裹,如 {"name": "Alice", "age": 25}
  • 数组(Array):有序值列表,用 [] 包裹,如 [1, "text", true]
  • 值(Value):可以是字符串、数字、布尔值、null、对象或数组。

在 JSONCPP 中,所有 JSON 数据均通过 Json::Value 类表示。

3.JsonCpp 介绍

Jsoncpp 库主要是用于实现 Json 格式数据的序列化和反序列化,它实现了将多个数据对象组织成为 json 格式字符串,以及将 Json 格式字符串解析得到多个数据对象的功能。

先看一下 Json 数据对象类的表示

  • 功能:存储任意 JSON 数据,支持动态类型判断。
  • 常用方法
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(); // 判断类型bool isObject() const;bool isArray() const;bool isString() const;
};

生成器(序列化接口 – Writer)

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;
}// 使用如下:
Json::StreamWriterBuilder builder;
builder.settings_["indentation"] = "  "; // 缩进两空格
std::string jsonStr = Json::writeString(builder, root);

解析器(反序列化接口–Reader)

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::CharReaderBuilder builder;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
JSONCPP_STRING errs;
bool success = reader->parse(jsonStr, jsonStr + strlen(jsonStr), &root, &errs);

小结,主要用的 三个类 如下:

  1. Json::Value类:中间数据存储类

    • 就需要先存储到 Json::Value 对象中如果要将数据对象进行序列化,如果要将数据传进行反序列化,就是解析后,将数据对象放入到J Json::Value 对象中
  2. Json::StreamWriter类:用于进行数据序列化

    • Json::StreamWriter::write() 序列化函数

    • Json::StreamWriterBuilder类: Json::StreamWriter 工厂类 – 用于生产 Json:.StreamWriter 对象

  3. Json::CharReader类:反序列化类

    • Json::CharReader::parse() 反序列化函数
    • Json::CharReaderBuilderJson::CharReader工厂类-用于生产 Json::.CharReader 对象

4.JsonCpp的使用

序列化(C++ 对象 -> JSON)

序列化是将 C++ 对象转换为 JSON 格式的字符串。我们可以通过 Json::Value 类来构建 JSON 对象,然后使用 Json::StreamWriterJson::FastWriter 来生成 JSON 字符串。

#include <iostream>
#include <json/json.h>int main() {// 创建一个 Json::Value 对象Json::Value root;// 添加一些键值对root["name"] = "Alice";root["age"] = 30;root["is_student"] = false;// 创建一个数组Json::Value languages;languages.append("C++");languages.append("Python");languages.append("JavaScript");root["languages"] = languages;// 使用 FastWriter 将 Json::Value 转换为 JSON 字符串Json::FastWriter fastWriter;std::string jsonString = fastWriter.write(root);// 输出 JSON 字符串std::cout << "Serialized JSON: " << jsonString << std::endl;return 0;
}

序列化结果

Serialized JSON: {"age":30,"is_student":false,"languages":["C++","Python","JavaScript"],"name":"Alice"}

反序列化(JSON -> C++ 对象

反序列化是将 JSON 字符串解析为 Json::Value 对象,以便在 C++ 中访问其内容。我们可以使用 Json::ReaderJson::CharReader 来解析 JSON 字符串。

#include <iostream>
#include <json/json.h>int main() {// 假设我们有一个 JSON 字符串std::string jsonString = "{\"name\":\"Alice\",\"age\":30,\"is_student\":false,\"languages\":[\"C++\",\"Python\",\"JavaScript\"]}";// 创建一个 Json::Value 对象Json::Value root;Json::CharReaderBuilder readerBuilder;std::string errs;// 使用 CharReader 解析 JSON 字符串std::istringstream iss(jsonString);if (!parseFromStream(readerBuilder, iss, &root, &errs)) {std::cerr << "Failed to parse JSON: " << errs << std::endl;return -1;}// 访问 JSON 数据std::string name = root["name"].asString();int age = root["age"].asInt();bool isStudent = root["is_student"].asBool();// 获取数组Json::Value languages = root["languages"];std::cout << "Deserialized JSON:" << std::endl;std::cout << "Name: " << name << std::endl;std::cout << "Age: " << age << std::endl;std::cout << "Is Student: " << (isStudent ? "Yes" : "No") << std::endl;std::cout << "Languages: ";for (unsigned int i = 0; i < languages.size(); ++i) {std::cout << languages[i].asString() << " ";}std::cout << std::endl;return 0;
}

反序列化结果:

Deserialized JSON:
Name: Alice
Age: 30
Is Student: No
Languages: C++ Python JavaScript 

5. 总结

  • 序列化 :通过 Json::Value 构建 JSON 对象,并使用 Json::FastWriterJson::StreamWriter 将其转换为 JSON 字符串。
  • 反序列化 :通过 Json::ReaderJson::CharReader 将 JSON 字符串解析为 Json::Value 对象,然后可以通过 asString()asInt() 等方法访问数据。

JsonCpp 是一个非常方便的库,适合在 C++ 项目中处理 JSON 数据。

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

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

相关文章

Ubuntu——执行echo $USE什么都不显示

问题&#xff1a;“执行 echo $USER 什么都不显示”&#xff1f; 一、原因分析 环境变量 $USER 未正确设置 $USER 是系统自动定义的环境变量&#xff0c;通常用于表示当前登录的用户名。若该变量未设置或为空&#xff0c;执行 echo $USER 会无输出。可能场景&#xff1a; 用户通…

uni-app学习笔记五--vue3插值表达式的使用

vue3快速上手导航&#xff1a;简介 | Vue.js 模板语法 插值表达式 最基本的数据绑定形式是文本插值&#xff0c;它使用的是“Mustache”语法 (即双大括号)&#xff1a; <span>Message: {{ msg }}</span> 双大括号标签会被替换为相应组件实例中 msg 属性的值。同…

【PSINS工具箱】基于工具箱的单独GNSS导航、单独INS导航、两者结合组合导航,三种导航的对比程序。附完整的代码

本文给出基于PSINS工具箱的单独GNSS导航、单独INS导航、两者结合组合导航(153EKF)的程序。并提供三者的轨迹对比、误差对比。 文章目录 运行结果MATLAB代码代码的简单介绍简介2. 平均绝对误差 (MAE)主要模块运行结果 三轴轨迹图: 各轴误差曲线: 命令行窗口的结果输出: …

C. scanf 函数基础

scanf 函数 1. scanf 函数基础1.1 函数原型与头文件1.2 格式化输入的基本概念2.1 常见格式说明符整数格式说明符浮点数格式说明符字符和字符串格式说明符其他格式说明符2.2 格式说明符的高级用法宽度修饰符精度修饰符跳过输入字段宽度组合修饰符对齐修饰符实际应用示例3.2 精度…

spring cloud loadbalancer实现机房感知的负载均衡

1 概述 在同城多机房情景下&#xff0c;各个机房各自部署一套微服务集群&#xff0c;正常情况下微服务调用在本机房闭环。在如下某些灾难情景&#xff0c;可以尝试拉远调用以最大程度维持业务连续性&#xff0c;这些情景例如&#xff1a; A机房多个服务器宕机。应用由于BUG发…

vue中,created和mounted两个钩子之间调用时差值受什么影响

在 Vue 中&#xff0c;created 和 mounted 是两个生命周期钩子&#xff0c;它们之间的调用时差主要受以下几个因素影响&#xff1a; &#x1f7e2; 1. 模板复杂度与渲染耗时&#xff08;最主要因素&#xff09; mounted 的触发时间是在组件的 DOM 被挂载之后&#xff08;也就是…

Linux篇 第2章Linux基础指令

Linux篇 第2章Linux基础指令 文章目录 前言一、基础的一些命令1.pwd2.mkdir3.ls4.cd5.clear 二、ls1.ls -l2.ls -a3.ls -l -a 三、touch四、 cd1.cd /2.cd ..3.cd ~4. cd - 五、tree1. Linux系统文件的结构2.绝对路径和相对路径 六、mkdir -p七、rmdir&#xff08;没啥用&#…

Scrapyd 详解:分布式爬虫部署与管理利器

Scrapyd 是 Scrapy 官方提供的爬虫部署与管理平台&#xff0c;支持分布式爬虫部署、定时任务调度、远程管理爬虫等功能。本文将深入讲解 Scrapyd 的核心功能、安装配置、爬虫部署流程、API 接口使用&#xff0c;以及如何结合 Scrapy-Redis 实现分布式爬虫管理。通过本文&#x…

国产免费工作流引擎star 6.5k,Warm-Flow升级1.7.2(新增案例和修复缺陷)

文章目录 主要更新内容项目介绍功能思维导图设计器流程图演示地址官网Warm-Flow视频 主要更新内容 [feat] 开启流程实例&#xff0c;新增流程定义是否存在校验[feat] 新增合同签订流程案例[feat] 新增企业采购流程案例[update] mybatis-plus逻辑删除&#xff0c;删除值和未删除…

数据仓库Hive

1.数据仓库 1.1数据仓库的概念 数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持管理决策。 面向主题。操作型数据库的数据组织面向事务处理任务&#xff0c;而数据仓库中的数据按照一定的…

dify 连接不上ollama An error occurred during credentials validation:

三大报错 An error occurred during credentials validation: HTTPConnectionPool(hosthost.docker.internal, port11434): Max retries exceeded with url: /api/chat (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x7f26fc3c00b0&…

uniapp 生成海报二维码 (微信小程序)

先下载qrcodenpm install qrcode 调用 community_poster.vue <template><view class"poster-page"><uv-navbar title"物业推广码" placeholder autoBack></uv-navbar><view class"community-info"><text clas…

如何理解编程中的递归、迭代与回归?

作为编程初学者&#xff0c;递归、迭代和回归这三个概念常常让人感到困惑。本文将通过生活化的比喻、Python代码示例和直观的对比&#xff0c;帮助你彻底理解这三个重要概念及其应用场景。 一、从生活比喻理解核心概念 1. 递归&#xff08;Recursion&#xff09;—— 俄罗斯套…

Android Studio 模拟器配置方案

Android Studio 模拟器配置方案 1.引言2.使用Android Studio中的模拟器3.使用国产模拟器1.引言 前面介绍【React Native基础环境配置】的时候需要配置模拟器,当时直接使用了USB调试方案,但是有些时候可能不太方便连接手机调试,比如没有iPhone调不了ios。接下来说明另外两种可…

uniapp(vue3)动态计算swiper高度封装自定义hook

// useCalculateSwiperHeight.ts import { ref, onMounted } from vue;export function useCalculateSwiperHeight(headerSelector: string .header-search, tabsWrapperSelector: string .u-tabs .u-tabs__wrapper) {const swiperHeight ref<number>(0);// 封装uni.g…

从代码学习深度学习 - 转置卷积 PyTorch版

文章目录 前言基本操作填充、步幅和多通道填充 (Padding)步幅 (Stride)多通道总结前言 在卷积神经网络(CNN)的大家族中,我们熟悉的卷积层和汇聚(池化)层通常会降低输入特征图的空间维度(高度和宽度)。然而,在许多应用场景中,例如图像的语义分割(需要对每个像素进行分…

c语言第一个小游戏:贪吃蛇小游戏06

实现贪吃蛇四方向的风骚走位 实现代码 #include <curses.h> #include <stdlib.h> struct snake{ int hang; int lie; struct snake *next; }; struct snake *head; struct snake *tail; int key; int dir; //全局变量 #define UP 1 //这个是宏定义&a…

django的权限角色管理(RBAC)

在 Django 中&#xff0c;User、Group 和 Permission 是权限系统的核心组件。下面通过代码示例演示它们的 CRUD&#xff08;创建、读取、更新、删除&#xff09; 操作&#xff1a; 一、User 模型 CRUD from django.contrib.auth.models import User# 创建用户 user User.obje…

解决docker alpine缺少字体的问题 Could not initialize class sun.awt.X11FontManager

制作的springboot项目镜像&#xff0c;缺少字体报错Could not initialize class sun.awt.X11FontManager 原因镜像中缺少字体 解决&#xff1a; 制作镜像时&#xff0c;添加字体库&#xff0c;Dockerfile文件 中添加如下内容 注意&#xff1a; jdk版本一定要使用&#xff0…

MQTT 在Spring Boot 中的使用

在 Spring Boot 中使用 MQTT 通常会借助 Spring Integration 项目提供的 MQTT 支持。这使得 MQTT 的集成可以很好地融入 Spring 的消息驱动和企业集成模式。 以下是如何在 Spring Boot 中集成和使用 MQTT 的详细步骤&#xff1a; 前提条件&#xff1a; MQTT Broker&#xff…