🚀 RapidJSON 完整学习指南
📚 目录
🔑 基础概念
RapidJSON 的三个核心类
            
            
              cpp
              
              
            
          
          // 1. Document - JSON文档的根(类似一个JSON对象容器)
rapidjson::Document document;
// 2. Value - JSON值(可以是对象、数组、字符串、数字等)
rapidjson::Value value;
// 3. Allocator - 内存分配器(RapidJSON需要它来分配内存)
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();JSON 的5种类型
            
            
              cpp
              
              
            
          
          kNullType       // null
kFalseType      // false
kTrueType       // true
kObjectType     // { "key": value }
kArrayType      // [ value, value, ... ]
kStringType     // "string"
kNumberType     // 123, 3.14🛠 创建JSON对象
方式1:基础创建
            
            
              cpp
              
              
            
          
          // 第1步:创建文档
rapidjson::Document document;
// 第2步:初始化为对象类型
document.SetObject();
// 第3步:获取分配器
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
// 第4步:添加键值对
document.AddMember("name", "John", allocator);
document.AddMember("age", 30, allocator);
document.AddMember("active", true, allocator);
// 结果: {"name":"John","age":30,"active":true}方式2:添加字符串(需要特殊处理)
            
            
              cpp
              
              
            
          
          std::string myString = "Hello World";
// ❌ 错误方式(会导致内存问题)
// document.AddMember("msg", myString, allocator);
// ✅ 正确方式1:使用SetString
rapidjson::Value stringValue;
stringValue.SetString(myString.c_str(), myString.size(), allocator);
document.AddMember("msg", stringValue, allocator);
// ✅ 正确方式2:简洁写法
document.AddMember(
    "msg",
    rapidjson::Value().SetString(myString.c_str(), myString.size(), allocator),
    allocator
);方式3:添加嵌套对象
            
            
              cpp
              
              
            
          
          // 创建嵌套对象
rapidjson::Value personObj(rapidjson::kObjectType);
personObj.AddMember("firstName", "John", allocator);
personObj.AddMember("lastName", "Doe", allocator);
// 添加到主文档
document.AddMember("person", personObj, allocator);
/* 结果:
{
  "person": {
    "firstName": "John",
    "lastName": "Doe"
  }
}
*/方式4:添加数组
            
            
              cpp
              
              
            
          
          // 创建数组
rapidjson::Value arrayValue(rapidjson::kArrayType);
// 添加元素
arrayValue.PushBack(10, allocator);
arrayValue.PushBack(20, allocator);
arrayValue.PushBack(30, allocator);
// 添加到文档
document.AddMember("numbers", arrayValue, allocator);
/* 结果:
{
  "numbers": [10, 20, 30]
}
*/方式5:数组中添加对象
            
            
              cpp
              
              
            
          
          rapidjson::Value itemsArray(rapidjson::kArrayType);
// 创建第一个对象
rapidjson::Value item1(rapidjson::kObjectType);
item1.AddMember("id", 1, allocator);
item1.AddMember("name", "Item 1", allocator);
itemsArray.PushBack(item1, allocator);
// 创建第二个对象
rapidjson::Value item2(rapidjson::kObjectType);
item2.AddMember("id", 2, allocator);
item2.AddMember("name", "Item 2", allocator);
itemsArray.PushBack(item2, allocator);
document.AddMember("items", itemsArray, allocator);
/* 结果:
{
  "items": [
    {"id": 1, "name": "Item 1"},
    {"id": 2, "name": "Item 2"}
  ]
}
*/📖 操作JSON
添加成员 - AddMember()
            
            
              cpp
              
              
            
          
          // 基本用法
document.AddMember("key", value, allocator);
// 支持的数据类型
document.AddMember("string", "value", allocator);      // 字符串
document.AddMember("int", 42, allocator);              // 整数
document.AddMember("double", 3.14, allocator);         // 浮点数
document.AddMember("bool", true, allocator);           // 布尔值
document.AddMember("null", rapidjson::Value(), allocator);  // null值检查成员是否存在 - HasMember()
            
            
              cpp
              
              
            
          
          if (document.HasMember("name")) {
    std::cout << "name exists" << std::endl;
}
// 安全的获取值
if (document.HasMember("name") && document["name"].IsString()) {
    std::string name = document["name"].GetString();
}删除成员 - RemoveMember()
            
            
              cpp
              
              
            
          
          document.RemoveMember("oldField");🔍 读取JSON
读取文本字段
            
            
              cpp
              
              
            
          
          // 方式1:直接访问
std::string name = document["name"].GetString();
// 方式2:安全访问(检查存在性)
if (document.HasMember("name") && document["name"].IsString()) {
    std::string name = document["name"].GetString();
}读取数字字段
            
            
              cpp
              
              
            
          
          int age = document["age"].GetInt();          // 整数
double salary = document["salary"].GetDouble();  // 浮点数读取布尔字段
            
            
              cpp
              
              
            
          
          bool active = document["active"].GetBool();读取对象字段
            
            
              cpp
              
              
            
          
          // JSON: {"person": {"name": "John"}}
std::string personName = document["person"]["name"].GetString();读取数组字段
            
            
              cpp
              
              
            
          
          // 方式1:通过GetArray()
const rapidjson::Value& array = document["numbers"].GetArray();
for (const auto& item : array) {
    int num = item.GetInt();
    std::cout << num << std::endl;
}
// 方式2:直接遍历
for (const auto& item : document["numbers"].GetArray()) {
    std::cout << item.GetInt() << std::endl;
}类型检查
            
            
              cpp
              
              
            
          
          if (value.IsString()) { std::cout << "是字符串" << std::endl; }
if (value.IsInt()) { std::cout << "是整数" << std::endl; }
if (value.IsDouble()) { std::cout << "是浮点数" << std::endl; }
if (value.IsBool()) { std::cout << "是布尔值" << std::endl; }
if (value.IsArray()) { std::cout << "是数组" << std::endl; }
if (value.IsObject()) { std::cout << "是对象" << std::endl; }
if (value.IsNull()) { std::cout << "是null" << std::endl; }🔄 序列化与反序列化
序列化(转换为字符串)
            
            
              cpp
              
              
            
          
          // 步骤1:创建StringBuffer来存储结果
rapidjson::StringBuffer buffer;
// 步骤2:创建Writer并写入文档
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
// 步骤3:获取JSON字符串
std::string jsonString = buffer.GetString();
std::cout << jsonString << std::endl;反序列化(从字符串解析)
            
            
              cpp
              
              
            
          
          std::string jsonString = R"({"name": "John", "age": 30})";
// 步骤1:创建新文档
rapidjson::Document doc;
// 步骤2:解析JSON字符串
doc.Parse(jsonString.c_str());
// 步骤3:检查是否解析成功
if (doc.HasParseError()) {
    std::cerr << "Parse error!" << std::endl;
    return;
}
// 步骤4:访问解析后的数据
std::string name = doc["name"].GetString();
int age = doc["age"].GetInt();💡 你的代码详解
现在让我为你详细讲解你的 setImageList() 函数:
            
            
              cpp
              
              
            
          
          void setImageList(std::string deviceId, std::list<image> list) {
    using namespace rapidjson;
    
    // ========== 第1步:创建文档 ==========
    Document document;
    document.SetObject();
    
    // ========== 第2步:设置消息头 ==========
    // address: 指定接收端处理该消息的处理器类型为 "imageplayer"
    document.AddMember("address", "imageplayer", document.GetAllocator());
    
    // action: 指定执行什么操作为 "setImageList"
    document.AddMember("action", "setImageList", document.GetAllocator());
    
    // ========== 第3步:创建数据对象 ==========
    Value data(kObjectType);
    
    // 添加目标设备ID
    data.AddMember(
        "to", 
        rapidjson::Value().SetString(
            deviceId.c_str(), 
            deviceId.size(), 
            document.GetAllocator()
        ), 
        document.GetAllocator()
    );
    
    // ========== 第4步:创建图片列表数组 ==========
    Value listValue(kArrayType);
    
    // 遍历输入的图片列表
    for (auto it : list) {
        // 为每个图片创建对象
        Value item(kObjectType);
        
        // 添加图片ID
        item.AddMember(
            "id", 
            rapidjson::Value().SetString(
                it.id.c_str(), 
                it.id.size(), 
                document.GetAllocator()
            ), 
            document.GetAllocator()
        );
        
        // 添加图片URL(文件路径)
        item.AddMember(
            "url", 
            rapidjson::Value().SetString(
                it.url.c_str(), 
                it.url.size(), 
                document.GetAllocator()
            ), 
            document.GetAllocator()
        );
        
        // 添加图片名称
        item.AddMember(
            "name", 
            rapidjson::Value().SetString(
                it.name.c_str(), 
                it.url.size(),  // ⚠️ 注意:这里可能是个BUG,应该是 it.name.size()
                document.GetAllocator()
            ), 
            document.GetAllocator()
        );
        
        // 将该图片对象添加到数组
        listValue.PushBack(item, document.GetAllocator());
    }
    
    // ========== 第5步:将列表添加到数据对象 ==========
    data.AddMember("list", listValue, document.GetAllocator());
    
    // ========== 第6步:将数据添加到文档 ==========
    document.AddMember("data", data, document.GetAllocator());
    
    // ========== 第7步:序列化为JSON字符串 ==========
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    document.Accept(writer);
    std::string str = buffer.GetString();
    
    // ========== 第8步:发送消息 ==========
    HHCastServerCore::getInstance()->sendMessage(str);
}输出示例
            
            
              json
              
              
            
          
          {
  "address": "imageplayer",
  "action": "setImageList",
  "data": {
    "to": "device_123",
    "list": [
      {
        "id": "img_001",
        "url": "C:/images/photo1.jpg",
        "name": "photo1.jpg"
      },
      {
        "id": "img_002",
        "url": "C:/images/photo2.png",
        "name": "photo2.png"
      }
    ]
  }
}🐛 你的代码中的问题
            
            
              cpp
              
              
            
          
          // ❌ 问题:name字段的大小使用了错误的值
item.AddMember(
    "name", 
    rapidjson::Value().SetString(
        it.name.c_str(), 
        it.url.size(),  // ⚠️ 应该是 it.name.size()
        document.GetAllocator()
    ), 
    document.GetAllocator()
);
// ✅ 修正后:
item.AddMember(
    "name", 
    rapidjson::Value().SetString(
        it.name.c_str(), 
        it.name.size(),  // 使用正确的size
        document.GetAllocator()
    ), 
    document.GetAllocator()
);📋 常用操作速查表
| 操作 | 代码示例 | 说明 | 
|---|---|---|
| 创建文档 | Document doc; doc.SetObject(); | 初始化空对象 | 
| 添加键值对 | doc.AddMember("key", value, allocator); | 添加成员 | 
| 获取字符串 | doc["key"].GetString() | 读取字符串值 | 
| 获取整数 | doc["key"].GetInt() | 读取整数值 | 
| 创建数组 | Value arr(kArrayType); | 创建空数组 | 
| 添加到数组 | arr.PushBack(value, allocator); | 向数组添加元素 | 
| 遍历数组 | for(auto& item : doc["arr"].GetArray()) | 循环遍历 | 
| 序列化 | StringBuffer buf; Writer w(buf); doc.Accept(w); | 转JSON字符串 | 
| 反序列化 | Document doc; doc.Parse(str.c_str()); | 从字符串解析 | 
| 检查成员 | doc.HasMember("key") | 检查键是否存在 | 
希望这能帮助你理解 RapidJSON!有任何疑问欢迎继续提问。