《RAPIDJSON:让 C++ 轻松解析 JSON》
宝子们,今天咱来瞅瞅 RAPIDJSON 这个超厉害的 C++ 库。它就像是一个超快速的“翻译官”,能把 JSON 格式的数据迅速翻译成咱 C++ 程序能懂的语言,让咱们可以轻松地处理各种复杂的数据,无论是开发网络应用,还是处理配置文件,它都能派上大用场,让咱的编程之路更加顺畅。
一、啥是 JSON 和 RAPIDJSON
JSON 是啥呢? 简单说,它就是一种数据格式,就像一个特别规整的小仓库,里面可以放各种数据,比如数字、字符串、数组、对象这些。比如说,{"name":"小明","age":18},这就是一个简单的 JSON 数据,里面有名字和年龄两个信息。
那 RAPIDJSON 呢? 它就是一个 C++ 库,专门用来解析 JSON 数据的。就像一个超级聪明的小助手,能快速地把 JSON 仓库里的东西拿出来,按照咱想要的方式整理好,供咱的 C++ 程序使用。
二、解析简单 JSON 数据示例
#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include <iostream>
#include <cstdio>
int main() {
// 这是一个简单的 JSON 字符串,就像一个写好的货物清单
const char* json = "{\"name\":\"小红\",\"age\":20}";
// 用 RAPIDJSON 创建一个文档对象,这就像是准备一个空箱子来装解析后的货物
rapidjson::Document doc;
// 让这个文档对象解析 JSON 字符串,就像把货物按照清单放进箱子里
doc.Parse(json);
// 检查解析是否成功,如果成功就像箱子装满了正确的货物
if (doc.HasParseError()) {
std::cerr << "JSON 解析出错!" << std::endl;
return 1;
}
// 从解析后的文档中取出数据,就像从箱子里拿出东西
std::string name = doc["name"].GetString();
int age = doc["age"].GetInt();
std::cout << "姓名:" << name << std::endl;
std::cout << "年龄:" << age << std::endl;
return 0;
}
代码运行结果:控制台会输出:
姓名:小红
年龄:20
小贴士:在写 JSON 字符串的时候,一定要注意引号、逗号这些标点符号,要是写错了,就像货物清单写错了,解析的时候就会出错。而且,获取数据的时候,要根据数据的类型用正确的方法,比如字符串用 GetString
,整数用 GetInt
,别弄混了,不然也拿不到正确的数据。
三、从文件读取 JSON 数据
#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include <iostream>
#include <cstdio>
int main() {
// 打开一个 JSON 文件,这里假设 "data.json" 在当前目录下,这就像打开一个装满货物的仓库大门
FILE* fp = fopen("data.json", "r");
if (!fp) {
std::cerr << "无法打开文件!" << std::endl;
return 1;
}
// 创建一个读取流,就像在仓库门口放了一个传送带,准备把货物传出来
char readBuffer[65536];
rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer));
// 创建文档对象并解析文件中的 JSON 数据,就像把传送带上的货物放进箱子里并整理好
rapidjson::Document doc;
doc.ParseStream(is);
if (doc.HasParseError()) {
std::cerr << "JSON 解析出错!" << std::endl;
fclose(fp);
return 1;
}
// 假设文件里的 JSON 数据是一个数组,我们遍历这个数组,就像检查仓库里一排一排的货物
if (doc.IsArray()) {
for (rapidjson::SizeType i = 0; i < doc.Size(); ++i) {
// 取出每个对象的 "name" 和 "age" 字段,就像从每个货物包裹里拿出特定的东西
std::string name = doc[i]["name"].GetString();
int age = doc[i]["age"].GetInt();
std::cout << "姓名:" << name << ",年龄:" << age << std::endl;
}
}
fclose(fp);
return 0;
}
代码运行结果:如果 "data.json" 文件里的内容是一个 JSON 数组,比如:
[{"name":"小刚","age":22},{"name":"小美","age":19}]
控制台会输出:
姓名:小刚,年龄:22
姓名:小美,年龄:19
小贴士:打开文件的时候,要检查文件路径是否正确,不然找不到文件就没办法解析了。而且读取流的缓冲区大小要合适,如果文件里的 JSON 数据很大,缓冲区太小可能会导致数据读取不完全,就像传送带太短,货物运不完。
四、构建 JSON 数据
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
int main() {
// 创建一个 JSON 文档对象,这就像准备一个空的货物清单表格
rapidjson::Document doc;
// 设置这个对象为一个 JSON 对象,就像在表格上写上这是一个完整的货物清单
doc.SetObject();
// 添加 "name" 和 "age" 字段到对象中,就像往清单里填写货物信息
rapidjson::Value name("小李", doc.GetAllocator());
doc.AddMember("name", name, doc.GetAllocator());
doc.AddMember("age", 25, doc.GetAllocator());
// 创建一个字符串缓冲区,用来存放生成的 JSON 字符串,就像准备一个小盒子来装写好的清单
rapidjson::StringBuffer buffer;
// 创建一个漂亮的写入器,就像找了一个写字漂亮的人来把清单写得整整齐齐
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
// 让写入器把文档对象写成 JSON 字符串,就像让写字的人把清单抄到纸上
doc.Accept(writer);
std::cout << buffer.GetString() << std::endl;
return 0;
}
代码运行结果:控制台会输出:
{
"name": "小李",
"age": 25
}
小贴士:添加成员的时候,要注意使用正确的分配器,不然可能会出现内存问题。而且如果想要生成更紧凑的 JSON 字符串,可以用普通的 Writer
代替 PrettyWriter
,但那样输出的字符串就没有这么整齐好看了,就像字写得快了可能就不那么工整,但内容是一样的。
五、实际应用场景
比如说我们在做一个天气应用,从网络上获取的天气数据通常是 JSON 格式的。用 RAPIDJSON 就能快速解析这些数据,把温度、湿度、天气状况等信息提取出来,然后在应用的界面上显示给用户。
再比如开发一个游戏,游戏的配置文件用 JSON 格式来存储各种设置,像角色的初始属性、游戏难度等级、画面显示设置等。通过 RAPIDJSON 可以方便地读取这些配置信息,让游戏按照玩家的喜好进行初始化设置,是不是很方便呢?
六、实践练习
自己创建一个包含多个学生信息(姓名、年龄、成绩)的 JSON 文件,然后用 RAPIDJSON 读取并计算这些学生的平均成绩,输出到控制台。
构建一个 JSON 数据,包含一个人的基本信息(姓名、年龄、爱好)和一个朋友列表(每个朋友也是一个包含姓名和年龄的对象),然后把这个 JSON 数据输出到文件里。
宝子们,RAPIDJSON 的功能还有很多很多,今天只是简单地介绍了一部分。要真正掌握它,就得自己动手敲代码,多去尝试不同的功能和用法。
今天的 C++ 学习之旅就到这里啦!记得动手敲代码。祝大家学习愉快,C++ 学习节节高!