本文由 AI 辅助生成,内容已验证可用
概述
RapidJSON 是一个 C++ 的 JSON 解析器及生成器,灵感来自 RapidXml。
核心特点:
- 高性能:使用 SIMD 指令加速解析
- 头文件库:无需编译,直接包含即可使用
- 内存友好:支持原位解析,减少内存分配
- 标准兼容:支持 JSON 标准 RFC7159 和 ECMA-404
- 跨平台:支持各大编译器和操作系统
官方文档:RapidJSON 主页
快速开始
安装
RapidJSON 是纯头文件库,只需下载并包含头文件即可:
# 方式一:直接下载
git clone https://github.com/Tencent/rapidjson.git
# 方式二:使用 vcpkg
vcpkg install rapidjson
# 方式三:使用 CMake FetchContent
include(FetchContent)
FetchContent_Declare(
rapidjson
GIT_REPOSITORY https://github.com/Tencent/rapidjson.git
GIT_TAG master
)
FetchContent_MakeAvailable(rapidjson)包含头文件
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include <iostream>
using namespace rapidjson;核心 API
1. 解析 JSON 字符串
// 从字符串解析
const char* json = R"({
"name": "小明",
"age": 25,
"skills": ["C++", "Python", "Rust"],
"active": true
})";
Document doc;
doc.Parse(json);
// 检查解析错误
if (doc.HasParseError()) {
std::cerr << "解析错误: " << doc.GetParseError() << std::endl;
return -1;
}2. 访问 JSON 值
// 获取对象成员
assert(doc.HasMember("name"));
assert(doc["name"].IsString());
std::string name = doc["name"].GetString();
// 获取数值
int age = doc["age"].GetInt();
bool active = doc["active"].GetBool();
// 获取数组
const Value& skills = doc["skills"];
assert(skills.IsArray());
for (SizeType i = 0; i < skills.Size(); i++) {
std::cout << "Skill: " << skills[i].GetString() << std::endl;
}
// 使用迭代器遍历
for (Value::ConstMemberIterator itr = doc.MemberBegin();
itr != doc.MemberEnd(); ++itr) {
std::cout << itr->name.GetString() << ": ";
// 根据 value 类型输出
}3. 创建 JSON 文档
Document doc;
doc.SetObject();
// 添加字符串
Document::AllocatorType& allocator = doc.GetAllocator();
doc.AddMember("name", "小明", allocator);
// 添加数值
doc.AddMember("age", 25, allocator);
// 添加布尔值
doc.AddMember("active", true, allocator);
// 创建数组
Value skills(kArrayType);
skills.PushBack("C++", allocator);
skills.PushBack("Python", allocator);
doc.AddMember("skills", skills, allocator);
// 创建嵌套对象
Value address(kObjectType);
address.AddMember("city", "北京", allocator);
address.AddMember("zip", "100000", allocator);
doc.AddMember("address", address, allocator);4. 序列化输出
// 方式一:紧凑格式
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
doc.Accept(writer);
std::cout << buffer.GetString() << std::endl;
// 方式二:美化格式(带缩进)
StringBuffer buffer;
PrettyWriter<StringBuffer> prettyWriter(buffer);
doc.Accept(prettyWriter);
std::cout << buffer.GetString() << std::endl;进阶用法
原位解析(In-situ Parsing)
减少内存分配,直接修改原始 JSON 字符串:
char json[] = R"({"name":"小明","age":25})";
Document doc;
doc.ParseInsitu(json); // 直接在原字符串上解析
// 注意:原字符串会被修改自定义内存分配器
// 使用内存池分配器,提升性能
MemoryPoolAllocator<> allocator;
Document doc(&allocator);处理大文件(流式解析)
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
// 读取大文件
FILE* fp = fopen("large.json", "rb");
char readBuffer[65536];
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
Document doc;
doc.ParseStream(is);
fclose(fp);
// 写入大文件
FILE* fp2 = fopen("output.json", "wb");
char writeBuffer[65536];
FileWriteStream os(fp2, writeBuffer, sizeof(writeBuffer));
PrettyWriter<FileWriteStream> writer(os);
doc.Accept(writer);
fclose(fp2);JSON Schema 验证
#include "rapidjson/schema.h"
Document sd;
sd.Parse(R"({
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "age"]
})");
SchemaDocument schema(sd);
Document doc;
doc.Parse(R"({"name":"小明","age":25})");
SchemaValidator validator(schema);
if (!doc.Accept(validator)) {
// 验证失败,输出错误信息
StringBuffer sb;
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
printf("Invalid schema: %s\n", sb.GetString());
printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
}类型判断与转换
类型判断 API
Value v;
v.IsNull(); // 是否为 null
v.IsFalse(); // 是否为 false
v.IsTrue(); // 是否为 true
v.IsBool(); // 是否为布尔值
v.IsObject(); // 是否为对象
v.IsArray(); // 是否为数组
v.IsString(); // 是否为字符串
v.IsNumber(); // 是否为数值
v.IsInt(); // 是否为 int
v.IsUint(); // 是否为 unsigned int
v.IsInt64(); // 是否为 int64_t
v.IsUint64(); // 是否为 uint64_t
v.IsDouble(); // 是否为 double数值获取 API
v.GetInt(); // 获取 int
v.GetUint(); // 获取 unsigned int
v.GetInt64(); // 获取 int64_t
v.GetUint64(); // 获取 uint64_t
v.GetDouble(); // 获取 double
v.GetBool(); // 获取 bool
v.GetString(); // 获取 const char*
v.GetStringLength(); // 获取字符串长度常见问题
1. 中文乱码问题
RapidJSON 原生支持 UTF-8,确保源文件编码为 UTF-8:
// 使用 UTF-8 编码保存文件
const char* json = R"({"name":"小明"})";2. 内存泄漏问题
使用内存池分配器时,注意生命周期:
void ProcessJson() {
MemoryPoolAllocator<> allocator;
Document doc(&allocator);
// ... 使用 doc
// 离开作用域,自动释放
}3. 性能优化建议
- 使用
ParseInsitu()减少内存分配 - 重用 Document 和 Allocator 对象
- 对于大量小 JSON,使用内存池分配器
- 启用 SIMD 优化(需要编译器支持)
完整示例
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include <iostream>
using namespace rapidjson;
int main() {
// 1. 创建 JSON 文档
Document doc;
doc.SetObject();
Document::AllocatorType& allocator = doc.GetAllocator();
// 2. 添加数据
doc.AddMember("project", "RapidJSON Demo", allocator);
doc.AddMember("version", 1.0, allocator);
Value tags(kArrayType);
tags.PushBack("JSON", allocator);
tags.PushBack("C++", allocator);
tags.PushBack("高性能", allocator);
doc.AddMember("tags", tags, allocator);
// 3. 序列化输出
StringBuffer buffer;
PrettyWriter<StringBuffer> writer(buffer);
doc.Accept(writer);
std::cout << "生成的 JSON:\n" << buffer.GetString() << std::endl;
// 4. 解析 JSON
Document parsedDoc;
parsedDoc.Parse(buffer.GetString());
// 5. 访问数据
std::cout << "\n解析结果:\n";
std::cout << "Project: " << parsedDoc["project"].GetString() << std::endl;
std::cout << "Version: " << parsedDoc["version"].GetDouble() << std::endl;
return 0;
}输出结果:
{
"project": "RapidJSON Demo",
"version": 1.0,
"tags": ["JSON", "C++", "高性能"]
}
解析结果:
Project: RapidJSON Demo
Version: 1.0相关链接
总结
RapidJSON 是一个高性能、易用、功能完善的 C++ JSON 库,适合:
✅ 需要高性能 JSON 解析的项目
✅ 嵌入式或内存受限环境
✅ 只需头文件即可集成的场景
✅ 需要流式解析大文件的场景
如果你的项目需要处理 JSON,RapidJSON 是一个非常值得考虑的选择。