当前位置: 首页 > news >正文

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.lryc.cn/news/608064.html

相关文章:

  • hyper-v实战系列:第一代虚拟机转第二代步骤
  • 深入理解 Docker 容器网络:为什么用 host 网络模式能解决连通性问题?
  • yolo 、Pytorch (5)IOU
  • Git、Gitee、GitHub、GitLab完整讲解:从基础到进阶
  • web:js的模块导出/导入
  • 开疆智能Profinet转Modbus网关连接信捷PLC从站配置案例
  • K8S部署ELK(二):部署Kafka消息队列
  • 深入 Go 底层原理(六):垃圾回收(GC)
  • ubuntu22.04离线一键安装gpu版docker
  • 开源列式分布式数据库clickhouse
  • pyqt5显示任务栏菜单并隐藏主窗口,环境pyqt5+vscode
  • CS课程项目设计7:基于Canvas交互友好的五子棋游戏
  • 从AI智能体出发,重构数据中台:迈向Agentic时代的数据能力体系
  • Docker容器中文PDF生成解决方案
  • Oracle 11gR2 Clusterware应知应会
  • 分布式事务----spring操作多个数据库,事务以及事务回滚还有用吗
  • Oracle 11g RAC集群部署手册(二)
  • Token系列 - 再谈稳定币
  • mac 安装pytho3 和pipx
  • 讲一讲Spring核心三大组件IOC、Bean、AOP
  • 我的世界模组开发教程——物品item(1)
  • Vuex 4.0:Vue.js 应用的状态管理新篇章
  • 深度学习核心:神经网络-激活函数 - 原理、实现及在医学影像领域的应用
  • K8S部署ELK(一):部署Filebeat日志收集器
  • SCI 绘图实用 RGB 配色方案:多组比较
  • [Windows] 微软.Net运行库离线合集包 Microsoft .Net Packages AIO v13.05.25
  • Vue3+ts自定义指令
  • 从毫秒到真义:构建工业级RAG系统的向量检索优化指南
  • 入门MicroPython+ESP32:ESP32烧录MicroPython固件
  • Python进阶(5):类与继承