c++ 使用 rapidjson 生成 json 并解析

概述

使用 rapidjson 生成 json 并对其进行解析。

常用函数

AddMember

  • 功能:往对象中添加一个键值对。
  • 函数原型
GenericValue& rapidjson::GenericValue< Encoding, Allocator >::AddMember(    
    GenericValue< Encoding, Allocator > &   name,
    GenericValue< Encoding, Allocator > &   value,
    Allocator & allocator 
)   
  • 函数参数
    • name 是键的名称
    • value 是对应键的值
    • allocator 用来分配内存的分配器,必须与前面使用的相同。

SetString

  • 功能:将此值设置为字符串,且复制原字符串。
  • 函数原型
GenericValue& rapidjson::GenericValue< Encoding, Allocator >::SetString(
  const Ch *    s,
  SizeType  length,
  Allocator &   allocator 
)           
  • 函数参数
    • s 是原字符串
    • length 是原字符串的长度,包括后面的空字符
    • allocator 分配器

代码

#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>
#include "rapidjson/prettywriter.h"
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"

using namespace std;
using namespace rapidjson;

//-----------------------------------------------------------------------------
void AddBasicType(Document &d, Document::AllocatorType & allocator)
{
    d.AddMember("digit", 3, allocator);           // 添加整型数据
    d.AddMember("height", 170.5, allocator);      // 添加浮点类型
    d.AddMember("subject1", "math", allocator);   // 添加字符串类型,常量方式

    string strSubject = "English";
    Value valueSubject(kStringType);
    valueSubject.SetString(strSubject.c_str(), strSubject.size(), allocator);

    if (!valueSubject.IsNull())
    {
        d.AddMember("subject2", valueSubject, allocator); // 添加字符串类型,变量方式,不能直接对变量进行添加,类型不对
    }
}

//-----------------------------------------------------------------------------
void AddObjectType(Document &d, Document::AllocatorType & allocator)
{
    Value valueObject(kObjectType);
    valueObject.AddMember("sex", "male", allocator);
    valueObject.AddMember("weight", 95, allocator);
    d.AddMember("info", valueObject, allocator);
}

//-----------------------------------------------------------------------------
void AddStringArrayType(Document &d, Document::AllocatorType & allocator)
{
    Value valueStr(kStringType);      // 单个字符串
    Value valueStrArray(kArrayType);  // 字符串数组

    string strExtraSubject1 = "计算机";
    string strExtraSubject2 = "音乐";
    string strExtraSubject3 = "体育";

    valueStr.SetString(strExtraSubject1.c_str(), strExtraSubject1.size(), allocator);
    valueStrArray.PushBack(valueStr, allocator);

    valueStr.SetString(strExtraSubject2.c_str(), strExtraSubject2.size(), allocator);
    valueStrArray.PushBack(valueStr, allocator);

    valueStr.SetString(strExtraSubject3.c_str(), strExtraSubject3.size(), allocator);
    valueStrArray.PushBack(valueStr, allocator);

    d.AddMember("extraSubject", valueStrArray, allocator);
}

//-----------------------------------------------------------------------------
void AddObjectArrayType(Document &d, Document::AllocatorType & allocator)
{
    Value valueObjectArray(kArrayType);
    for (int i = 0; i < 3; i++)
    {
        Value valueSingleObject(kObjectType);
        valueSingleObject.AddMember("score", i * 40, allocator);
        if (i == 0)
        {
            valueSingleObject.AddMember("difficulty", "hard", allocator);
        }
        else if (i == 1)
        {
            valueSingleObject.AddMember("difficulty", "abnormal", allocator);
        }
        else 
        {
            valueSingleObject.AddMember("difficulty", "easy", allocator);
        }
        valueObjectArray.PushBack(valueSingleObject, allocator);
    }
    d.AddMember("subjectInfo", valueObjectArray, allocator);
}

//-----------------------------------------------------------------------------
void ParseBasicType(Document &d, string jsonData)
{
    if (!d.Parse(jsonData.data()).HasParseError())
    {
        // 解析整型
        if (d.HasMember("digit") && d["digit"].IsInt())
        {
            cout << "digit = " << d["digit"].GetInt() << endl;
        }

        // 解析浮点型
        if (d.HasMember("height") && d["height"].IsDouble())
        {
            cout << "height = " << d["height"].GetDouble() << endl;
        }

        // 解析字符串类型
        if (d.HasMember("subject1") && d["subject1"].IsString())
        {
            cout << "subject1 = " << d["subject1"].GetString() << endl;
        }

        if (d.HasMember("subject2") && d["subject1"].IsString())
        {
            cout << "subject2 = " << d["subject2"].GetString() << endl;
        }
    }
}

//-----------------------------------------------------------------------------
void ParseObjectType(Document &d, string jsonData)
{
    if (d.HasMember("info") && d["info"].IsObject())
    {
        const Value& resInfo = d["info"]; // 获取对象
        if (resInfo.HasMember("sex") && resInfo["sex"].IsString())
        {
            cout << "resInfo.sex = " << resInfo["sex"].GetString() << endl;
        }
        if (resInfo.HasMember("weight") && resInfo["weight"].IsInt())
        {
            cout << "resInfo.weight = " << resInfo["weight"].GetInt() << endl;
        }
    }
}

//-----------------------------------------------------------------------------
void ParseStringArrayType(Document &d, string jsonData)
{
    if (d.HasMember("extraSubject") && d["extraSubject"].IsArray())
    {
        const Value& valueStrArray = d["extraSubject"];
        size_t len = valueStrArray.Size(); // 获取数组长度

        for (size_t i = 0; i < len; i++)
        {
            cout << "extraSubject[" << i << "] = " << valueStrArray[i].GetString() << endl;
        }
    }
}

//-----------------------------------------------------------------------------
void ParseObjectArrayType(Document &d, string jsonData)
{
    if (d.HasMember("subjectInfo") && d["subjectInfo"].IsArray())
    {
        const Value& valueObjectArray = d["subjectInfo"]; // 获取对象数组
        size_t len = valueObjectArray.Size();
        for (size_t i = 0; i < len; i++)
        {
            const Value& object = valueObjectArray[i]; // 每一个元素都是一个对象

            if (object.IsObject())
            {
                cout << "subjectInfo[" << i << "]: ";
                if (object.HasMember("score") && object["score"].IsInt())
                {
                    cout << "score = " << object["score"].GetInt();
                }
                if (object.HasMember("difficulty") && object["difficulty"].IsString())
                {
                    cout << " difficulty = " << object["difficulty"].GetString();
                }
            }
            cout << endl;
        }
    }
}

//-----------------------------------------------------------------------------
int main()
{
    Document d;
    d.SetObject();
    wstring wsValue;
    Document::AllocatorType &allocator = d.GetAllocator(); // 获取分配器
    
    AddBasicType(d, allocator);         // 添加基本类型
    AddObjectType(d, allocator);        // 添加对象类型,对象中有基本数据类型
    AddStringArrayType(d, allocator);   // 添加字符串数组类型,数组中的每一个元素是一个字符串
    AddObjectArrayType(d, allocator);   // 添加对象数组类型,数组中的每一个元素是一个对象

    // StringBuffer是一个简单的输出流。它分配一个内存缓冲区,供写入整个JSON。
    // 可使用GetString()来获取该缓冲区。
    StringBuffer strBuf;
    Writer<StringBuffer> writer(strBuf);
    d.Accept(writer);

    string jsonData = strBuf.GetString();
    cout << jsonData << endl << endl;

    ParseBasicType(d, jsonData);        // 解析基本类型
    ParseObjectType(d, jsonData);       // 解析对象类型
    ParseStringArrayType(d, jsonData);  // 解析字符串数组类型
    ParseObjectArrayType(d, jsonData);  // 解析对象数组类型
}

生成的 json 数据

{
  "digit": 3,
  "height": 170.5,
  "subject1": "math",
  "subject2": "English",
  "info": {
    "sex": "male",
    "weight": 95
  },
  "extraSubject": [
    "计算机",
    "音乐",
    "体育"
  ],
  "subjectInfo": [
    {
      "score": 0,
      "difficulty": "hard"
    },
    {
      "score": 40,
      "difficulty": "abnormal"
    },
    {
      "score": 80,
      "difficulty": "easy"
    }
  ]
}

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354