rapidjson使用

41 篇文章 1 订阅
2 篇文章 0 订阅

简介

Rapidjson is a fast JSON parser/generator for C++ with both SAX/DOM style API.
其所有源代码都包含在源码包的include/rapidjson/include目录下,使用时只需要include相应的头文件即可。
详细的介绍见rapid官方文档

使用rapidjson解析json串

先看下rapidjson中的value有哪些类型, rapidjson中定义的类型的先后顺序为:
“Null”, “False”, “True”, “Object”, “Array”, “String”, “Number”
其中Number类型包含int, uint, int64, uint64, double

Type GetType()  const { return static_cast<Type>(data_.f.flags & kTypeMask); }    
bool IsNull()   const { return data_.f.flags == kNullFlag; }
bool IsFalse()  const { return data_.f.flags == kFalseFlag; }
bool IsTrue()   const { return data_.f.flags == kTrueFlag; }
bool IsBool()   const { return (data_.f.flags & kBoolFlag) != 0; }
bool IsObject() const { return data_.f.flags == kObjectFlag; }
bool IsArray()  const { return data_.f.flags == kArrayFlag; }
bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
bool IsInt()    const { return (data_.f.flags & kIntFlag) != 0; }
bool IsUint()   const { return (data_.f.flags & kUintFlag) != 0; }
bool IsInt64()  const { return (data_.f.flags & kInt64Flag) != 0; }
bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }

有了这个后,我们就可以根据dom节点的类型来解析出对应的value,伪代码如下如下:

#define ERROR -1
#define OK 0

string jsonstr = {"key":value, ...};
Document document;
if(document.Parse(jsonstr.c_str()).HasParseError())
{
	return ERROR;
}

const rapidjson::Value& value = document["key"]; //use [] operator to get node value
/** use FindMember function 
auto var = document.FindMember("key");
if(var != document.MemberEnd())
{
	rapidjson::Value& value = var->value;
}
*/
if(value.IsNull())
{
	...
}
else if(value.IsObject())
{
	//continue to parse 
	...
}else if(value.isString())
{
	cout << value.GetString();
}else if(value.isNumber())
{
	if(value.isInt())
	{...
	}else if(value.isUint())
	{...
	}else ...
	
}
...

另外,我们也可以实现一个打印json串内容的函数:

int printJsonString(string& jsonstr)
{
	Document document;
	if(document.Parse(json).HasParseError())
	{
		return -1;
	}
	static const char* kTypeNames[] = 
		{ "Null", "False", "True", "Object", "Array", "String", "Number" };
	for (auto& m : document.GetObject())
	{
		printf("Type of member %s is %s\n",
		m.name.GetString(), kTypeNames[m.value.GetType()]);
		if(m.value.isNull())
		{
			printf("key = %s, value = %s\n", m.name.GetString(), "null");
		}else if(m.value.isString())
		{	
			printf("key = %s, value = %s\n", m.name.GetString(), m.value.GetString());
		}else if(...)
		...
		
	}
	return 0;
}

上述解析的json串是通过string or char字符串输入的,如果json串来源于文件的话,就需要使用如下的方法调用Parse方法(详细使用说明参考rapidjson文件流):

#include "rapidjson/filereadstream.h"
#include <cstdio>
using namespace rapidjson;
FILE* fp = fopen("big.json", "rb"); // 非 Windows 平台使用 "r"
char readBuffer[65536];
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
Document d;
d.ParseStream(is);
fclose(fp);

使用rapidjson构造json串

有几种方法可用于构造json串:

  1. 通过rapidjson::Writer<rapidjson::StringBuffer>对象的’StartObject/EndObject’ Method.
int constructJsonStr1(string& outputStr) 
{ 
    rapidjson::StringBuffer json_str_buf; 
    rapidjson::Writer<rapidjson::StringBuffer> json_writer(json_str_buf); 
    json_writer.StartObject(); 
    json_writer.String("id"); 
    json_writer.Uint(0); 
    json_writer.String("name"); 
    json_writer.String("zhangsan"); 
 
    json_writer.String("data"); 
    json_writer.StartObject(); 
    json_writer.String("age"); 
    json_writer.Uint(20); 
    json_writer.String("province"); 
    json_writer.String("guangdong"); 
    json_writer.EndObject(); 
 
    json_writer.EndObject(); 
 
 	 outputStr = json_str_buf.GetString(); 
    cout << outputStr << endl; 
    return 0; 
} 

  1. 通过构造一个rapidjson::Document对象,使用rapidjson::Document及rapidjson::Value的’AddMember’ Method.
int constructJsonStr2()
{
    rapidjson::Document document;
    document.SetObject();
    rapidjson::Document::AllocatorType & allocator = document.GetAllocator();

    document.AddMember("id", 0, allocator);
    document.AddMember("name", rapidjson::StringRef("zhangsan"), allocator);

    rapidjson::Value data_obj(rapidjson::kObjectType);
    data_obj.AddMember("age", 20, allocator);
    data_obj.AddMember("province", rapidjson::StringRef("guangdong"), allocator);

    document.AddMember("data", data_obj, allocator);

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    document.Accept(writer);

    cout << buffer.GetString() << endl;
    return 0;
}
  1. 使用Document + Pointer
Document d;
// 使用 Set() 创建 DOM
Pointer("/project").Set(d, "RapidJSON");
Pointer("/stars").Set(d, 10);
// { "project" : "RapidJSON", "stars" : 10 }

p.s.:

  • PushBack及AddMember中使用了转移语义
  • copy-string与const-string
    当我们把一个 copy-string 赋值时, 调用含有 allocator 的 SetString() 重载函数.
Document document;
Value author;
char buffer[10];
int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // 动态创建的字符串。
author.SetString(buffer, len, document.GetAllocator());
memset(buffer, 0, sizeof(buffer));
// 清空 buffer 后 author.GetString() 仍然包含 "Milo Yip"

对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 SetString(),它没有 allocator 参数。对于字符串字面量(或字符数组常量),只需简单地传递字面量,又安全又高效:

Value s;
s.SetString("rapidjson");    // 可包含空字符,长度在编译萁推导
s = "rapidjson";  

对于字符指针,RapidJSON 需要作一个标记,代表它不复制也是安全的。可以使用 StringRef 函数

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值