rapidJson问题记录

一、赋值问题

...
Value subServesObj(kObjectType);
subServesObj = subListObj["reserves"];
...

//subListObj是Document的某一个节点;
//如果进行了上述赋值操作,则Document中的"reserves"字段的value将为null。
char szName[64];	
char szAge[64];	

Value Name(kStringType);
Name.SetString(szName, strlen(szName));
subObject.AddMember("Name", Name, allocator);

Value age(kStringType);
age.SetString(szAge, strlen(szAge));
subObject.AddMember("age", Name, allocator);//注意此处

//Value Name(kStringType)被add之后,不能再次被AddMember;
//如果再次被AddMember,age对应的value为空。

二、接收到的json需要修改某些字段名或类型再发出去

内部 ->-> 外部

如果以上json报文到我们的地方需要兼容字段,不要在原来的json上面进行Remove删除,再AddMember的操作,容易出现问题。

正确的操作方式是:重新建立一个document,将接收到的json报文进行解析,再将解析到的字段AddMember或PushBack到新document里。

Document doc;
doc.SetObject();
Document::AllocatorType& allocator = doc.GetAllocator();

//strRcvJson为一个数组类型的json
Document document	
document.Parse(strRcvJson.c_str());
if (document.HasParseError())
{
	printf("Parse strRcvJson failed!\n");
}
if(!document.IsArray())
{
	printf(" strRcvJson document is not array\n");
}
Value SendRcvJsonArr(kArrayType);
for( auto &subObj : document.GetArray())
{
	Value SendRcvJsonObj(kObjectType);
	if(subObj.HasMember("time") && subObj["time"].IsInt64())
	{
		long iTime = subObj["time"].GetInt64();
		Value time(kNumberType);
		time.SetInt64(iTime);
		SendRcvJsonObj.AddMember("time", time,allocator);
	}
	if(subObj.HasMember("ids") && subObj["ids"].IsArray())
	{
		Value SendIdsArr(kArrayType);
		SendIdsArr = subObj["ids"];
		SendRcvJsonObj.AddMember("ids", SendIdsArr, allocator);
	}
	if(subObj.HasMember("stringId") && subObj["stringId"].IsString())
	{
		string strStringId = subObj["stringId"].GetString();
		Value stringId(kStringType);			 stringId.SetString(strStringId.c_str(),strStringId.size(),allocator);
		SendRcvJsonObj.AddMember("stringId", stringId, allocator);
	}
	/*对于数组类型的value也可以这样解析添加,就是麻烦一点*/
	if(subObj.HasMember("dataList") && subObj["dataList"].IsArray())
	{
		Value SendDataArr(kArrayType);
		for( auto &subDataObj : subObj["dataList"].GetArray())
		{			
			SendDataArr.PushBack(subDataObj, allocator);
		}
		SendRcvJsonObj.AddMember("dataList", SendDataArr, allocator);
	}					
	SendRcvJsonArr.PushBack(SendRcvJsonObj,allocator);
}
doc.AddMember("sendJson", SendRcvJsonArr, allocator);

StringBuffer strBuffer;
Writer<StringBuffer>writer(strBuffer);
doc.Accept(writer);	
string pcBuf = strBuffer.GetString();

三、可以将一个Document 通过AddMember或PushBack添加到另一个Document中

这种情况要注意一下待添加的Document的生命周期问题,局部变量释放了就有问题了,到最后doc.Accept(writer)会core掉。

四、深拷贝

在上文中我们提到过,rapidJson进行赋值操作,原节点value将变为空,有时我们不希望源原节点变为null,还需要用到原节点。

比如判断原节点的某些字段的值(过滤),再决定是否要将原节点添加到新的document,这时我们需要用到深拷贝。

Move语意

rapidjson的Move语意,请浏览http://rapidjson.org/zhcn/md_doc_tutorial_8zh-cn.html#MoveSemantics。

示例:

rapidjson::Value a(123);
rapidjson::Value b(456);
b = a; // a变成Null,b变成数字123,这样的做法是基于性能考虑

除了上述示例的复制语句外,AddMember()和PushBack()也采用了Move语意。深复制Value:

Value v1("foo");
// Value v2(v1); // 不容许
Value v2(v1, a); // 制造一个克隆,v1不变
Document d;
v2.CopyFrom(d, a); // 把整个document复制至v2,d不变

rapidjson为了最大化性能,大量使用了浅拷贝,使用之前一定要了解清楚。如果采用了浅拷贝,特别要注意局部对象的使用,以防止对象已被析构了,却还在被使用。

注:
1、当然,如果不用深复制,也可以暴力去解析此节点,再添加到新document。
2、如果仅仅是匹配字段,最好的方式是直接传引用,也不用深拷贝了,这个就看具体的场景了。

//传引用
Value &subObj = subListObj["object"];
//深拷贝
Document doc;//无特殊意义,用于reserves字段的深拷贝,为其提供内存分配器
Document::AllocatorType& allocator = doc.GetAllocator();
Value subObj(subListObj["object"], allocator)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值