Json Jsoncpp

文章目录

  • Json 介绍
  • Jsoncpp 介绍
    • Json::Value
    • 序列化接口
    • 反序列化接口
  • 序列化操作
  • 反序列化操作




Json 介绍


JSON(JavaScript Object Notation,JavaScript 对象表示法)是一种轻量级的数据交换格式,具有简洁、易读、跨平台等特点,广泛应用于前后端数据传输、配置文件、API 接口等场景。

核心特点:

  • 文本格式:基于纯文本,易于人类阅读和编写,也便于机器解析和生成。
  • 跨语言兼容:虽然源于 JavaScript,但几乎所有编程语言都有解析和生成 JSON 的库(如 Python 的 json 模块、Java 的 Jackson 等)。
  • 数据结构简单:仅支持两种核心结构:
    • 键值对集合(类似对象、字典):用 {} 包裹,键值对以 : 分隔,格式为 {"key": value}
    • 有序值列表(类似数组):用 [] 包裹,元素以 , 分隔,格式为 [value1, value2, ...]
  • 支持的数据类型:字符串(“string”)、数字(整数 / 浮点数,如 123、3.14)、布尔值(true/false)、null、对象、数组。

Json数据格式:

{"name": "Alice","age": 25,"is_student": false,"hobbies": ["reading", "coding"],"address": {"city": "Beijing","street": "Main St"}
}


Jsoncpp 介绍


Jsoncpp 是一个用于 C++ 语言的 JSON 解析库,提供了对 JSON 数据的读写、解析和生成功能,是 C++ 开发中处理 JSON 的常用工具。

核心功能

  • 解析 JSON 字符串 / 文件:将 JSON 格式的文本转换为 C++ 可操作的对象。
  • 生成 JSON 字符串 / 文件:将 C++ 中的数据结构转换为 JSON 格式。
  • 操作 JSON 数据:支持增删改查 JSON 中的键值对、数组元素等。

主要类和方法

  • Json::Value:最核心的类,用于表示 JSON 中的值(可以是对象、数组、字符串、数字等)。

    • 示例:Json::Value root; root["name"] = "Alice";(创建键值对)
  • Json::FastWriter / Json::StyledWriter:用于将 Json::Value 转换为 JSON 字符串。(这是旧版序列化接口,这里写出来给大家见一见,我们学习使用还是选择新版的)

    • FastWriter:生成紧凑的无缩进字符串。
    • StyledWriter:生成带缩进的易读字符串。
  • Json::Reader:用于解析 JSON 字符串或文件,将其转换为 Json::Value 对象。(这是旧版反序列化接口,这里写出来给大家见一见,我们学习使用还是选择新版的)

    • 示例:Json::Reader reader; reader.parse(json_str, root);(解析字符串到 root)

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

Json::Value

我们先来看一下 Json 数据对象类的表示(只列举了部分重要的接口):

class Json::Value {// 赋值运算符重载:将另一个Value对象的值赋给当前对象Value &operator=(const Value &other);// 键值对操作:通过字符串键获取/设置值// 示例:val["name"] = "xx"; (设置)或 std::string name = val["name"].asString();(获取)Value& operator[](const std::string& key);Value& operator[](const char* key);// 移除指定键的成员Value removeMember(const char* key);// 数组操作:通过索引获取数组元素(常量版本)// 示例:int firstScore = val["score"][0].asInt();const Value& operator[](ArrayIndex index) const;// 向数组末尾添加元素// 示例:val["score"].append(88);Value& append(const Value& value);// 获取数组元素个数// 示例:int scoreCount = val["score"].size();ArrayIndex size() const;// 类型转换方法std::string asString() const;      // 转换为std::string,示例:std::string name = val["name"].asString();const char* asCString() const;     // 转换为C风格字符串,示例:const char* name = val["name"].asCString();Int asInt() const;                 // 转换为整数,示例:int age = val["age"].asInt();float asFloat() const;             // 转换为浮点数,示例:float weight = val["weight"].asFloat();bool asBool() const;               // 转换为布尔值,示例:bool ok = val["ok"].asBool();
};
  • Json::Value 是 Jsoncpp 库中最核心的类,如果要将数据对象进行序列化,就需要先存储到 Json::Value 对象中。
  • 如果要将一个 Json 数据串进行反序列化(就是解析完成后),也需要将数据放到Json::Value 对象中。

简单来说,它是 JSON 数据在 C++ 中的 “容器” 和 “操作接口”,所有对 JSON 的创建、修改、访问都通过这个类完成。


序列化接口

// JSON_API 是 Jsoncpp 中用于导出类的宏(跨平台兼容)
// StreamWriter 是一个纯虚基类,定义了 JSON 写入流的接口
class JSON_API StreamWriter {
public:// 纯虚函数:将 JSON 数据(root)写入输出流(sout)// 返回值:写入的字符数(成功)或负数(失败)virtual int write(Value const& root, std::ostream* sout) = 0;// 虚析构函数(基类通常需要定义,确保派生类析构正确)virtual ~StreamWriter() = default;
};// StreamWriterBuilder 是 StreamWriter 的工厂类
// 继承自 StreamWriter::Factory(工厂接口)
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
public:// 工厂方法:创建并返回一个 StreamWriter 实例// 用于将 Json::Value 转换为 JSON 字符串并写入流virtual StreamWriter* newStreamWriter() const;// 虚析构函数virtual ~StreamWriterBuilder() = default;
};


反序列化接口

// JSON_API 宏导出宏,用于跨平台动态链接
// CharReader 是纯虚基类,定义了解析JSON字符串的接口
class JSON_API CharReader {
public:// 纯虚函数:解析JSON字符串并填充到Value对象// 参数://   beginDoc - JSON字符串的起始地址//   endDoc   - JSON字符串的结束地址(指向最后一个字符的下一位)//   root     - 输出参数,解析后的JSON数据将存储到该Value对象//   errs     - 输出参数,解析错误信息(若解析失败)// 返回值:true表示解析成功,false表示失败virtual bool parse(char const* beginDoc, char const* endDoc,Value* root, std::string* errs) = 0;// 虚析构函数,确保派生类析构函数能正确调用virtual ~CharReader() = default;
};// CharReaderBuilder 是CharReader的工厂类
// 继承自CharReader::Factory(工厂接口)
class JSON_API CharReaderBuilder : public CharReader::Factory {
public:// 工厂方法:创建并返回一个CharReader实例// 用于解析JSON字符串为Json::Value对象virtual CharReader* newCharReader() const;// 虚析构函数virtual ~CharReaderBuilder() = default;
};


序列化操作


前面已经介绍过接口了,所以这里直接演示使用方式:

#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
using namespace std;// 实现数据的序列化
void serialize(const Json::Value& value, string& output) 
{std::stringstream ss;// 先实例化一个工厂类Json::StreamWriterBuilder writer;// 通过工厂类创建一个流写入器std::unique_ptr<Json::StreamWriter> jsonWriter(writer.newStreamWriter());// 将数据写入到字符串流中jsonWriter->write(value, &ss);// 获取字符串流中的内容output = ss.str();
}int main()
{std::string name = "小明";int age = 18;std::string sex = "男";double score[3] = {63, 78.5, 87};// 创建一个Json对象Json::Value fav;fav["书籍"] = "三国演义";fav["运动"] = "篮球";fav["音乐"] = "探窗";Json::Value student;student["姓名"] = name;student["年龄"] = age;student["性别"] = sex;student["成绩"] = Json::arrayValue; // 创建一个数组for (int i = 0; i < 3; ++i) {student["成绩"].append(score[i]); // 向数组中添加元素}student["爱好"] = fav;// 序列化Json对象std::string output;serialize(student, output);std::cout << "Serialized JSON: \n" << output << std::endl;return 0;
}

在这里插入图片描述


反序列化操作


#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
using namespace std;// 实现数据的反序列化
void unserialize(const std::string& input, Json::Value& value) 
{// 实例化工厂类Json::CharReaderBuilder readerBuilder;// 创建解析器std::unique_ptr<Json::CharReader> jsonReader(readerBuilder.newCharReader());// 直接使用input解析,无需经过stringstream中转std::string errs;if (!jsonReader->parse(input.c_str(), input.c_str() + input.size(), &value, &errs)) {std::cerr << "Failed to parse JSON: " << errs << std::endl;}
}int main()
{std::string input = R"({"姓名": "小明","年龄": 18,"性别": "男","成绩": [63, 78.5, 87],"爱好": {"书籍": "三国演义","运动": "篮球","音乐": "探窗"}})";Json::Value student;// 反序列化Json字符串unserialize(input, student);// 输出各个字段std::cout << "姓名: " << student["姓名"].asString() << std::endl;std::cout << "年龄: " << student["年龄"].asInt() << std::endl;std::cout << "性别: " << student["性别"].asString() << std::endl;std::cout << "成绩: ";for (Json::ArrayIndex i = 0; i < student["成绩"].size(); ++i) {  // 更规范的数组遍历方式std::cout << student["成绩"][i].asDouble() << " ";}std::cout << std::endl;std::cout << "爱好: \n";std::cout << "  书籍: " << student["爱好"]["书籍"].asString() << std::endl;std::cout << "  运动: " << student["爱好"]["运动"].asString() << std::endl;std::cout << "  音乐: " << student["爱好"]["音乐"].asString() << std::endl;return 0;
}

在这里插入图片描述

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

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

相关文章

openwrt下安装istore(基于pve)

openwrt下安装istore&#xff08;基于pve&#xff09;ssh连接到openwrt&#xff0c;用如下命令安装istore&#xff1a;opkg update || exit 1cd /tmpwget https://github.com/linkease/openwrt-app-actions/raw/main/applications/luci-app-systools/root/usr/share/systools/i…

2025年Python Web框架之争:Django、Flask还是FastAPI,谁将主宰未来?

文章概要 作为一名Python开发者&#xff0c;我经常被问到同一个问题&#xff1a;在2025年&#xff0c;Django、Flask和FastAPI哪个框架更值得使用&#xff1f;随着技术的快速发展&#xff0c;这个问题的答案也在不断变化。本文将全面比较这三个主流Python Web框架的特点、性能、…

高级11-Java日志管理:使用Log4j与SLF4J

在现代Java应用开发中&#xff0c;日志&#xff08;Logging&#xff09;是系统监控、调试、故障排查和性能分析的核心工具。一个高效、灵活、可配置的日志系统&#xff0c;不仅能帮助开发者快速定位问题&#xff0c;还能为运维团队提供宝贵的运行时信息。在Java生态系统中&…

sc-atac的基础知识(0)

sc-atac的基础知识 **fragment**是ATAC-seq实验中的一个重要概念&#xff0c;它指的是通过Tn5转座酶对DNA分子进行酶切&#xff0c;然后经由双端测序得到的序列。根据Tn5插入导致的偏移从read比对得到的位置推断出fragment的起始和结束位置。根据之前的报道&#xff0c;Tn5转座…

Python从入门到精通计划Day01: Python开发环境搭建指南:从零开始打造你的“数字厨房“

目录一、配置你的「魔杖」&#xff1a;Python 3.x安装1.1 跨平台安装指南1.2 验证你的「法力值」二、选择你的「魔法工坊」&#xff1a;IDE配置2.1 VS Code&#xff1a;轻量级实验室2.2 PyCharm&#xff1a;专业级法师塔三、施展第一个「魔咒」&#xff1a;Hello World3.1 基础…

MCP Agent 工程框架Dify初探

目录引言一、Dify是什么二、为什么使用Dify三、使用Dify要怎么做1、聊天助手2、Agent2.1 Function calling&#xff08;函数调用&#xff09;和 ReAct 两种推理模式的区别2.1.1 技术本质与工作流程对比2.1.2 优缺点对比2.1.3 适用场景与选择依据2.2 LangChain 的 Agent 实现原理…

无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析

原创声明本文为原创技术解析&#xff0c;核心技术参数与架构设计引用自《陌讯技术白皮书》&#xff0c;转载请注明来源。一、行业痛点&#xff1a;无人机光伏巡检的 "识别困境"光伏电站的大规模铺设推动了无人机巡检的普及&#xff0c;但实际作业中仍面临三大技术瓶颈…

机动车占道识别准确率提升 29%:陌讯动态轮廓感知算法实战解析

原创声明本文为原创技术解析&#xff0c;核心技术参数与架构设计引用自《陌讯技术白皮书》&#xff0c;禁止未经授权的转载与改编。一、行业痛点&#xff1a;机动车占道治理的技术瓶颈城市交通监控中&#xff0c;机动车占用应急车道、公交车道等违规行为已成为影响通行效率与交…

UNet改进(29):记忆增强注意力机制在UNet中的创新应用-原理、实现与性能提升

记忆增强注意力机制概述 记忆增强注意力是一种结合了外部记忆模块的注意力机制,它使神经网络能够存储和检索长期知识,而不仅仅是依赖当前的输入特征。这种机制特别适合需要保持长期依赖关系的任务,如医学图像分割,其中模型需要记住不同样本中出现的常见模式。 核心组件 记…

使用Python开发Ditto剪贴板数据导出工具

前言在日常工作中&#xff0c;我们经常需要处理大量的剪贴板数据。Ditto作为一款优秀的剪贴板管理软件&#xff0c;帮助我们保存了丰富的历史记录。但有时我们需要将这些数据导出进行进一步分析或备份&#xff0c;而Ditto本身并没有提供直观的批量导出功能。C:\pythoncode\new\…

【人工智能】提示词设计原则:简洁性、明确性、具体性如何平衡?

提示词设计原则&#xff1a;简洁性、明确性、具体性如何平衡&#xff1f;1. 提示词设计三大原则的核心内涵1.1 简洁性1.1.1 定义用最少的文字传递核心信息&#xff0c;避免冗余和不必要的描述。比如 “写 3 个春天的成语” 比 “我想让你写出来 3 个和春天有关系的成语词语” 更…

JS的作用域

文章目录一、为什么需要作用域&#xff1f;二、什么是 JS 作用域&#xff1f;2.1 什么是词法作用域和动态作用域&#xff1f;1. 词法作用域&#xff08;Lexical Scpoe&#xff09;2. 动态作用域2.2 JS 的作用域2.3 JS 作用域的分类1. 全局作用域2. 模块作用域3. 函数作用域4. 块…

OLTP,OLAP,HTAP是什么,数据库该怎么选

目录 OLTP&#xff08;Online Transaction Processing&#xff09;联机事务处理 OLAP&#xff08;Online Analytical Processing&#xff09;联机分析处理 非实时OLAP 实时OLAP HTAP&#xff08;Hybrid Transactional/Analytical Processing&#xff09; OLAP 和 OLTP 数…

【前端】CSS Flexbox布局示例介绍

CSS Flexbox&#xff08;弹性盒子&#xff09;简介 Flexbox 是一种一维布局模型&#xff0c;用于高效处理元素在容器内的空间分配、对齐和排序。它通过父容器&#xff08;flex container&#xff09;和子元素&#xff08;flex items&#xff09;的配合实现灵活响应式布局。核心…

Vue3核心语法基础

一、为什么要学 Composition API&#xff1f;在以前我们写代码用Vue2写&#xff1a;export default {data() {return { count: 0, msg: hello }},methods: {add() { this.count }},computed: {double() { return this.count * 2 }} }很明显 一个功能被拆成三块&#xff1a;data…

FSMC的配置和应用

一、FSMC 简介与工作原理FSMC&#xff08;Flexible Static Memory Controller&#xff09;是 STM32 微控制器中用于与外部静态存储器&#xff08;如 SRAM、PSRAM、NOR Flash、LCD 等&#xff09;进行通信的一个外设模块。1、支持的设备类型&#xff1a;SRAM / PSRAMNOR FlashNA…

Linux I/O 系统调用完整对比分析

Linux I/O 系统调用完整对比分析 1. 概述 Linux 提供了丰富的 I/O 系统调用&#xff0c;每种都有其特定的用途和优势。本文将详细分析这些系统调用的特点、使用场景和性能特征。 2. 系统调用详细对比 2.1 基本读写函数 pread/pwrite #include <unistd.h>// 位置指定…

TiDB集群部署

架构&#xff1a; tidb–3台&#xff0c;pd–3台&#xff0c;tikv–3台 8c16g200g 1x2.2x.2x7.124 1x2.2x.2x7.148 1x2.2x.2x7.87 1x2.2x.2x7.93 1x2.2x.2x7.127 1x2.2x.2x7.104 pd-3台 4c8g100g 1x2.2x.2x7.143 1x2.2x.2x7.132 1x2.2x.2x7.91 1、下载安装包 #注&#xff1a;我…

C#中对于List的多种排序方式

在 C# 中给 List<AI> 排序&#xff0c;只要 明确排序规则&#xff08;比如按某个字段、某几个字段、或外部规则&#xff09;&#xff0c;就能用下面几种常见写法。下面全部基于这个示例类&#xff1a;public class AI {public int country; // 国家编号public int pr…

Spring框架中Bean的生命周期:源码解析与最佳实践

第1章&#xff1a;Spring Bean生命周期概述1.1 什么是Spring Bean生命周期&#xff1f;定义&#xff1a;Spring Bean生命周期是指从Bean的创建、初始化、使用到销毁的完整过程&#xff0c;由Spring容器严格管理 。核心思想是Spring容器通过IoC&#xff08;控制反转&#xff09;…