【c++】rapidjson
1. 概念
- Document类代表整个DOM,每个 JSON 值都储存为 Value 类
#include "rapidjson/document.h"
using namespace rapidjson;
//把json字符串解析到doc
const char* json;
Document doc;
doc.Parse(json);
数据类型
//! Type of JSON value
enum Type {
kNullType = 0, //!< null
kFalseType = 1, //!< false
kTrueType = 2, //!< true
kObjectType = 3, //!< object
kArrayType = 4, //!< array
kStringType = 5, //!< string
kNumberType = 6 //!< number
};
判断类型
Document::IsNull()
Document::IsBool()
Document::IsObject()
Document::IsArray()
Document::IsString()
Document::IsNumber()
Document::IsInt()
Document::IsDouble()
使用默认构造函数创建一个 Value 或 Document,它的类型便会是 Null。要改变其类型,需调用 SetXXX() 或赋值操作
Value v; // Null
v.SetInt(10);
v = 10; // 简写,和上面的相同
构造Value及赋值
- 创建空Object或 Array。一次性使用 Value(Type)
Value o(kObjectType);
Value a(kArrayType);
- 构造赋值
Value b(true); // 调用 Value(bool)
Value i(-123); // 调用 Value(int)
Value u(123u); // 调用 Value(unsigned)
Value d(1.5); // 调用 Value(double)
赋值
- 字符串
函数原型:SetString(const char*, int, SizeType length, Allocator& allocator)
Value a(kNumberType);
a.SetInt(42);
a=Value().SetInt(42).Move();
std::string str = "hello";
Value b(kStringType);
b.SetString(str.c_str(), str.size(), doc.GetAllocator());
b=Value().SetString(str.c_str(), str.size(), doc.GetAllocator()).Move();
取值
- 通过
Value::name获取字段名,通过Value::value获取字段值。
auto bodyObj = bodyDoc.GetObject();
for(auto& m:body)
{
string col(m.name.GetString());
auto val = m.value.GetString();
}
- 取值前为了健壮性,一定要先判断字段是否存在,是否为null。
//Array
GetArray();
SizeType Capacity() const
bool Empty() const
你可以用整数字面量访问元素,如 a[0]、a[1]、a[2]
除了使用索引,也可使用迭代器来访问所有元素。
for (Value::ConstValueIterator iter = a.Begin(); iter != a.End(); ++iter)
{
if(!iter->IsNull()) cout<<iter->GetInt();
}
//String
GetString();
if(doc.HasMember("key") && !doc["key"].IsNull())
{
string str = doc["key"].IsString();
}
//Number
| bool IsUint() | unsigned GetUint() |
| --------------- | -------------------- |
| bool IsInt() | int GetInt() |
| bool IsUint64() | uint64_t GetUint64() |
| bool IsInt64() | int64_t GetInt64() |
| bool IsDouble() | double GetDouble() |
//Ojbect
operator[]
Value的拷贝使用的是移动语义
Value a(123);
Value b(456);
b = a; // a 变成 Null,b 变成数字 123。
添加元素
Object添加k-v:AddMember("key", Value, allocator),
Array添加元素:PushBack(Value, allocator)
Value如果用直接临时值会报错。临时对象是不能转换为正常的 Value 引用,我们加入了一个方便的 Move() 函数:
Value a(kArrayType);
Document::AllocatorType& allocator = document.GetAllocator();
// a.PushBack(Value(42), allocator); // 不能通过编译
a.PushBack(Value().SetInt(42), allocator); // fluent API
a.PushBack(Value(42).Move(), allocator); // 和上一行相同
Value b(kObjectType);
std::string str = "hello";
b.AddMember("key", Value().SetString(str.c_str(), str.size(), allocator), allocator);//key可以直接写字符串
b.AddMember(Value("key", allocator).Move(), Value().SetString(str.c_str(), str.size(), allocator), allocator);
b.AddMember(Value("key", allocator).Move(), Value(str.c_str(), str.size(), allocator).Move(), allocator);
2. 读写json文件
(1)从文件读到Document
#include "rapidjson/filereadstream.h"
#include <cstdio>
static tl::expected<Document, string> jsonDocFromFile(string const &file)
{
FILE *fp = fopen(file.c_str(), "r");
if (!fp)
return tl::make_unexpected("failed opening file: " + file);
char readBuf[1024];
FileReadStream frs(fp, readBuf, sizeof(readBuf));
Document doc;
if (doc.ParseStream<kParseCommentsFlag>(frs).HasParseError()) {
return tl::make_unexpected("jsonDocFromFile: invalid json file:" + file);
}
fclose(fp);
return std::move(doc);
}
(2)把Document写到文件
#include "rapidjson/filewritestream.h"
//#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include <cstdio>
static tl::expected<bool, string> saveToJsonFile(string const &jsonPath, Document const &doc)
{
FILE* fp = fopen(jsonPath.c_str(), "w");//清空写入(wb的b二进制)
if(!fp)
return tl::make_unexpected("failed opening file: " + jsonPath);
char writeBuf[1024];
FileWriteStream fws(fp, writeBuf, sizeof(writeBuf));
PrettyWriter<FileWriteStream> writer(fws);//PrettyWriter会自动设定换行等格式
//Writer<FileWriteStream> writer(fws);//紧凑
writer.SetMaxDecimalPlaces(6);
doc.Accept(writer);
fclose(fp);
return true;
}
(3)修改json
//修改json的devices数组
/*
"devices": [
{
"id": 1,
"ip": "127.0.0.1",
"device_port": 6666,
}
],
"server":"hello"
*/
void modifyJson(string jsonName, vector<Device> devicesUpdate)
{
// 读json
auto retReadJson = Config::jsonDocFromFile(jsonName);
if (!retReadJson.has_value())
{
cout<<"读取json文件失败: " + retReadJson.error()<<endl;
return;
}
Document &docSave = retReadJson.value();
if(!docSave.HasMember("devices") || !docSave["devices"].IsArray())
{
cout<<"json文件没有devices字段: " + retReadJson.error()<<endl;
return;
}
//修改devices字段
for(int i=0;i<devicesUpdate.size();i++)
{
Value& device = docSave["devices"][i];
if(!device.IsObject())
continue;
device["id"].SetInt(devicesUpdate[i].id);
device["device_ip"] = Value(devicesUpdate[i].devIp.c_str(), devicesUpdate[i].devIp.size(), docSave.GetAllocator()).Move();
device["device_port"] = Value().SetInt(devicesUpdate[i].devPort);
device["server_port"] = Value().SetInt(devicesUpdate[i].serverPort);
}
//写入到json文件
auto retWriteJson = Config::saveToJsonFile(jsonName, docSave);
if (!retWriteJson.has_value())
{
cout<<"保存到json文件失败: " + retWriteJson.error()<<endl;;
return;
}
else if (retWriteJson.value() == true) cout<<"更新json文件OK"<<endl;
return;
}
(4)将Document输出文本
// 将 Document 序列化为字符串
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
docSave.Accept(writer);
// 输出字符串到控制台
std::cout << buffer.GetString() << std::endl;

浙公网安备 33010602011771号