RapidJSON介绍

1.简介

RapidJSON 是一个 C++ 的 JSON 解析库,由腾讯开源。

  • 支持 SAX 和 DOM 风格的 API,并且可以解析、生成和查询 JSON 数据。
  • RapidJSON 快。它的性能可与strlen() 相比。可支持 SSE2/SSE4.2 加速。
  • RapidJSON 独立。它不依赖于 BOOST 等外部库。它甚至不依赖于STL。
  • RapidJSON 对内存友好。在大部分 32/64 位机器上,每个 JSON 值只占 16字节(除字符串外)。它预设使用一个快速的内存分配器,令分析器可以紧凑地分配内存。
  • RapidJSON 对 Unicode 友好。它支持UTF-8、UTF-16、UTF-32 (大端序/小端序),并内部支持这些编码的检测、校验及转码。例如,RapidJSON 可以在分析一个。
  • RapidJSON 是跨平台的。

2.环境搭建

下载地址:https://github.com/Tencent/rapidjson/tree/v1.1.0

这里使用的版本1.1.0

下载完成之后解压目录如下,将整个include目录拷贝到我们的工程目录下。

拷贝完成之后如下图所示:

配置文件路径。C/C++ ->常规 ->附加包含目录

3.代码示例

DOM接口示例

cpp 复制代码
#include "rapidjson/document.h"     // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include <iostream>

using namespace rapidjson;

int main()
{
	
	// 1. Parse a JSON text string to a document.
	const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
	printf("Original JSON:\n %s\n", json);

	Document document;  // Default template parameter uses UTF8 and MemoryPoolAllocator.

	// In-situ parsing, decode strings directly in the source string. Source must be string.
	char buffer[sizeof(json)];
	memcpy(buffer, json, sizeof(json));
	if (document.ParseInsitu(buffer).HasParseError())
		return 1;

	printf("\nParsing to document succeeded.\n");

	
	// 2. Access values in document. 

	printf("\nAccess values in document:\n");
	assert(document.IsObject());    // Document is a JSON value represents the root of DOM. Root can be either an object or array.

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

	// Since version 0.2, you can use single lookup to check the existing of member and its value:
	Value::MemberIterator hello = document.FindMember("hello");
	assert(hello != document.MemberEnd());
	assert(hello->value.IsString());
	assert(strcmp("world", hello->value.GetString()) == 0);
	(void)hello;

	assert(document["t"].IsBool());     // JSON true/false are bool. Can also uses more specific function IsTrue().
	printf("t = %s\n", document["t"].GetBool() ? "true" : "false");

	assert(document["f"].IsBool());
	printf("f = %s\n", document["f"].GetBool() ? "true" : "false");

	printf("n = %s\n", document["n"].IsNull() ? "null" : "?");

	assert(document["i"].IsNumber());   // Number is a JSON type, but C++ needs more specific type.
	assert(document["i"].IsInt());      // In this case, IsUint()/IsInt64()/IsUint64() also return true.
	printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]

	assert(document["pi"].IsNumber());
	assert(document["pi"].IsDouble());
	printf("pi = %g\n", document["pi"].GetDouble());

	{
		const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster.
		assert(a.IsArray());
		for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t.
			printf("a[%d] = %d\n", i, a[i].GetInt());

		int y = a[0].GetInt();
		(void)y;

		// Iterating array with iterators
		printf("a = ");
		for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
			printf("%d ", itr->GetInt());
		printf("\n");
	}

	// Iterating object members
	static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
	for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr)
		printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]);

	
	// 3. Modify values in document.

	// Change i to a bigger number
	{
		uint64_t f20 = 1;   // compute factorial of 20
		for (uint64_t j = 1; j <= 20; j++)
			f20 *= j;
		document["i"] = f20;    // Alternate form: document["i"].SetUint64(f20)
		assert(!document["i"].IsInt()); // No longer can be cast as int or uint.
	}

	// Adding values to array.
	{
		Value& a = document["a"];   // This time we uses non-const reference.
		Document::AllocatorType& allocator = document.GetAllocator();
		for (int i = 5; i <= 10; i++)
			a.PushBack(i, allocator);   // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.

		// Fluent API
		a.PushBack("Lua", allocator).PushBack("Mio", allocator);
	}

	// Making string values.

	// This version of SetString() just store the pointer to the string.
	// So it is for literal and string that exists within value's life-cycle.
	{
		document["hello"] = "rapidjson";    // This will invoke strlen()
		// Faster version:
		// document["hello"].SetString("rapidjson", 9);
	}

	// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
	Value author;
	{
		char buffer2[10];
		int len = sprintf(buffer2, "%s %s", "Milo", "Yip");  // synthetic example of dynamically created string.

		author.SetString(buffer2, static_cast<SizeType>(len), document.GetAllocator());
		// Shorter but slower version:
		// document["hello"].SetString(buffer, document.GetAllocator());

		// Constructor version: 
		// Value author(buffer, len, document.GetAllocator());
		// Value author(buffer, document.GetAllocator());
		memset(buffer2, 0, sizeof(buffer2)); // For demonstration purpose.
	}
	// Variable 'buffer' is unusable now but 'author' has already made a copy.
	document.AddMember("author", author, document.GetAllocator());

	assert(author.IsNull());        // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.

	
	// 4. Stringify JSON

	printf("\nModified JSON with reformatting:\n");
	StringBuffer sb;
	PrettyWriter<StringBuffer> writer(sb);
	document.Accept(writer);    // Accept() traverses the DOM and generates Handler events.
	puts(sb.GetString());
	return 0;
}

运行结果:

SAX接口示例:

cpp 复制代码
#include "rapidjson/document.h"     // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include "rapidjson/reader.h"
#include "rapidjson/error/en.h"
#include <iostream>
#include <string>
#include <map>

using namespace std;
using namespace rapidjson;

typedef map<string, string> MessageMap;

#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif

#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch - enum)
#endif

struct MessageHandler : public BaseReaderHandler<UTF8<>, MessageHandler>
{
	MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {}

	bool StartObject() 
	{
		switch (state_) 
		{
		case kExpectObjectStart:
			state_ = kExpectNameOrObjectEnd;
			return true;
		default:
			return false;
		}
	}

	bool String(const char* str, SizeType length, bool)
	{
		switch (state_) 
		{
		case kExpectNameOrObjectEnd:
			name_ = string(str, length);
			state_ = kExpectValue;
			return true;
		case kExpectValue:
			messages_.insert(MessageMap::value_type(name_, string(str, length)));
			state_ = kExpectNameOrObjectEnd;
			return true;
		default:
			return false;
		}
	}

	bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; }

	bool Default() { return false; } // All other events are invalid.

	MessageMap messages_;
	enum State
	{
		kExpectObjectStart,
		kExpectNameOrObjectEnd,
		kExpectValue
	}state_;
	std::string name_;
};

#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif

#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif

static void ParseMessages(const char* json, MessageMap& messages)
{
	Reader reader;
	MessageHandler handler;
	StringStream ss(json);
	if (reader.Parse(ss, handler))
		messages.swap(handler.messages_);   // Only change it if success.
	else 
	{
		ParseErrorCode e = reader.GetParseErrorCode();
		size_t o = reader.GetErrorOffset();
		cout << "Error: " << GetParseError_En(e) << endl;;
		cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl;
	}
}

int main()
{
	MessageMap messages;

	const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }";
	cout << json1 << endl;
	ParseMessages(json1, messages);

	for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr)
		cout << itr->first << ": " << itr->second << endl;

	cout << endl << "Parse a JSON with invalid schema." << endl;
	const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }";
	cout << json2 << endl;
	ParseMessages(json2, messages);

	return 0;
}

4.更多参考

libVLC 专栏介绍-CSDN博客

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍_qt opengl视频播放器-CSDN博客

QCharts -1.概述-CSDN博客

相关推荐
froginwe118 分钟前
PostgreSQL表达式的类型
开发语言
委婉待续11 分钟前
java抽奖系统(八)
java·开发语言·状态模式
deja vu水中芭蕾13 分钟前
嵌入式C面试
c语言·开发语言
爱码小白13 分钟前
PyQt5 学习方法之悟道
开发语言·qt·学习方法
aaasssdddd9615 分钟前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
发呆小天才O.oᯅ22 分钟前
YOLOv8目标检测——详细记录使用OpenCV的DNN模块进行推理部署C++实现
c++·图像处理·人工智能·opencv·yolo·目标检测·dnn
西猫雷婶33 分钟前
python学opencv|读取图像(十六)修改HSV图像HSV值
开发语言·python·opencv
weixin_537590451 小时前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet
lsx2024061 小时前
MVC 发布
开发语言
qincjun1 小时前
文件I/O操作:C++
开发语言·c++