您的位置:

rapidjson详细解析

Rapidjson是一个快速的C++ JSON解析器/生成器,它提供了更高效的内部数据结构和更快的序列化/反序列化速度。它支持SAX和DOM两种解析方式以及多种输出格式,能够满足不同场景下的需求。下面我们将从各个方面进行详细解析。

一、解析器

Rapidjson提供了两种解析器,SAX和DOM。

SAX解析器

SAX解析器是一种基于事件驱动的解析器,可以处理巨大的JSON数据而不会产生大量的内存占用。Rapidjson的SAX解析器使用JsonReader类的基于流的API来解析JSON。它能够快速的将JSON解析为token流,可以逐个地遍历每个token,从而实现在内存中处理JSON。使用SAX解析器可以提高解析速度,并减少内存占用。

DOM解析器

DOM解析器是将整个JSON解析为一个内存结构,方便随机存取JSON数据。使用DOM解析器可以获取JSON的所有信息,但是会占用大量的内存,不适合处理大型JSON数据。在使用DOM解析器时,需要将整个JSON文件加载到内存中,所以速度会比SAX解析器慢。

二、数据结构

当使用DOM解析器时,Rapidjson使用了一个内部结构来存储JSON数据,这个结构被称为GenericValue,它是一个具有一般性的、灵活的、自我描述的树状结构,可以使用不同的类型和对象操作来访问它。它支持所有的JSON数据类型,包括字符串、数字、布尔值、数组以及对象。

字符串

在GenericValue中,字符串是一个std::string对象。

数字

在GenericValue中,数字是一个double类型的对象。

布尔值

在GenericValue中,布尔值是一个bool类型的对象。

数组

在GenericValue中,数组是一个GenericArray对象,它包含了若干个GenericValue元素。可以使用std::vector的方式访问它们。

对象

在GenericValue中,对象是一个GenericObject对象,它包含了若干个键值对,每个键值对的键是一个字符串,值是一个GenericValue对象。可以使用std::map的方式访问它们。

三、输出格式

Rapidjson提供了多种输出格式,包括自定义缩进、空格、换行符等。可以通过OutputStream的Write()函数将JSON数据输出到文件系统或者网络流中。

美观的输出格式

为了方便读取和比较,可以利用JsonWriter的SetIndent()函数设置输出格式,例如:

rapidjson::StringBuffer sb;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
writer.SetIndent('\t', 1); // 设置缩进和空格数量
document.Accept(writer);
std::cout << sb.GetString() << std::endl;

紧凑的输出格式

在某些情况下,我们需要减少JSON的格式化,使JSON数据更紧凑。可以通过JsonWriter的SetFormatOptions()函数设置输出格式。例如:

rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
writer.SetFormatOptions(rapidjson::kFormatCompact);
document.Accept(writer);
std::cout << sb.GetString() << std::endl;

四、完整示例代码

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

int main() {
    const char* json = "{\"hello\": \"world\"}";
    Document document;
    document.Parse(json);

    assert(document.HasMember("hello"));
    assert(document["hello"].IsString());
    printf("hello = %s\n", document["hello"].GetString());

    StringBuffer sb;
    Writer<StringBuffer> writer(sb);
    document.Accept(writer);
    printf("%s\n", sb.GetString());

    return 0;
}