C++对象的JSON序列化与反序列化探索完结-列表的序列化与反序列化

在前两篇文章中,我们已经完成对普通对象以及复杂对象嵌套的序列化与反序列化,见如下地址:

C++对象的JSON序列化与反序列化探索

C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化


经过一番折腾,总算把带有列表的对象的序列化完成了,目前支持 list 和 vector 的列表,以及自定义的其他类型的列表,我们可以先来看看实现的效果。

复杂对象及带列表对象的序列号主要有如下几种:

1. 普通的list列表,如:list<string>

	list<string> testList;
	testList.push_back("33333333");
	testList.push_back("55555555");
	tvalue = CJsonObjectBase::DoArraySerialize<list<string>>(&testList);
	out = CJsonObjectBase::JsonValueToString(tvalue);
	AfxMessageBox(out.c_str());
序列化结果为:
["33333333","55555555"]

2. 复杂对象的列表,如list<CTestStru*>

Json::Value tvalue;
	std::string out;
	vector<CSubTestStruct*> testListSpecial;
	obj = new CSubTestStruct();
	obj->SubMsgID = 2;
	obj->SubMsgTitle = "333";
	testListSpecial.push_back(obj);
	obj = new CSubTestStruct();
	obj->SubMsgID = 3;
	obj->SubMsgTitle = "4444";
	testListSpecial.push_back(obj);	
	tvalue = CJsonObjectBase::DoArraySerialize<vector<CJsonObjectBase*>>((vector<CJsonObjectBase*>*)&testListSpecial);
	out = CJsonObjectBase::JsonValueToString(tvalue);
	AfxMessageBox(out.c_str());

[{"SubMsgID":2,"SubMsgTitle":"333"},{"SubMsgID":3,"SubMsgTitle":"4444"}]
此注需要注意的是,使用完毕后,一定要记得销毁列表中的对象:

for (vector<CSubTestStruct*>::iterator it = testListSpecial.begin(); it != testListSpecial.end(); ++ it)
	{
		delete (*it);
	}
反序列化:

void* GenerateTest(const string& name)
{
	return new CSubTestStruct(); 
}

CString strTest = "";
	string strTestEx = "[{\"SubMsgID\":2,\"SubMsgTitle\":\"2222\"},{\"SubMsgID\":4444,\"SubMsgTitle\":\"4444\"}]";
	Json::Reader reader;    
	Json::Value root;  
	if (reader.parse(strTestEx, root))  
	{
		vector<CSubTestStruct*> listObjTest;
		CJsonObjectBase::DoObjArrayDeSerialize<vector<CJsonObjectBase*>>("test", &listObjTest, root, GenerateTest);
		strTest.Format("count %d\r\nfirst subTitle:%s", listObjTest.size(), listObjTest.size() > 0 ? listObjTest[0]->SubMsgTitle.c_str() : "");
		AfxMessageBox(strTest);

		for (vector<CSubTestStruct*>::iterator it = listObjTest.begin(); it != listObjTest.end(); ++ it)
		{
			delete (*it);
		}
	}
打印结果:

count 2
first subTitle:2222
3. 在对象中包含普通及复杂的列表,如下:

struct CSubTestStruct : public CJsonObjectBase  
{  
	CSubTestStruct()  
	{  
		SubMsgID = 0;  
		SetPropertys();  
	}  
	
	ULONGLONG SubMsgID;  
	string SubMsgTitle;  
protected:  
	//子类需要实现此函数,并且将相应的映射关系进行设置   
	virtual void SetPropertys()  
	{  
		SetProperty("SubMsgID", asUInt64, &SubMsgID);  
		SetProperty("SubMsgTitle", asString, &SubMsgTitle);  
	}  
};  
struct CTestStruct : public CJsonObjectBase  
{  
	CTestStruct()  
	{  
		SetPropertys();  
	}  
	~CTestStruct()
	{
		for (vector<CSubTestStruct*>::iterator it = testListSpecial.begin(); it != testListSpecial.end(); ++ it)
		{
			delete (*it);
		}
	}
	ULONGLONG MsgID;  
	string MsgTitle;  
	string MsgContent;  
	CSubTestStruct subObj;  
	vector<INT> intList;
	list<string> testList;
	vector<CSubTestStruct*> testListSpecial;
protected:  
	CJsonObjectBase* GenerateJsonObjForDeSerialize(const string& propertyName)
	{
		if("testListSpecial" == propertyName)
		{
			return new CSubTestStruct();
		}
		return NULL;
	}
	//子类需要实现此函数,并且将相应的映射关系进行设置   
	virtual void SetPropertys()  
	{
		SetProperty("MsgID", asUInt64, &MsgID);  
		SetProperty("MsgTitle", asString, &MsgTitle);  
		SetProperty("MsgContent", asString, &MsgContent);  
		SetProperty("subObj", asJsonObj, &subObj);
		SetProperty("intList", asVectorArray, &intList);
	        SetProperty("testList", asListArray, &testList, asString);
	        SetProperty("testListSpecial", asVectorArray, &testListSpecial, asJsonObj);		
	} 	
};  
序列化代码:

CTestStruct stru;
	stru.MsgID = 11223344;
	stru.MsgTitle = "黑黑";
	stru.MsgContent = "哈哈";
	stru.testList.push_back("aaaa");
	stru.testList.push_back("bbbb");
	stru.intList.push_back(3333);
	CSubTestStruct* obj = new CSubTestStruct();
	obj->SubMsgID = 2;
	obj->SubMsgTitle = "333";
	stru.testListSpecial.push_back(obj);
	obj = new CSubTestStruct();
	obj->SubMsgID = 3;
	obj->SubMsgTitle = "4444";
	stru.testListSpecial.push_back(obj);
	CString strTest = stru.Serialize().c_str();
	AfxMessageBox(strTest);
打印结果:

{"MsgContent":"哈哈","MsgID":11223344,"MsgTitle":"黑黑","intList":[3333],"subObj":{"SubMsgID":0,"SubMsgTitle":""},"testList":["aaaa","bbbb"],"testListSpecial":[{"SubMsgID":2,"SubMsgTitle":"333"},{"SubMsgID":3,"SubMsgTitle":"4444"}]}
反序列化代码:

const char* pstr = "{\"MsgContent\":\"哈哈\",\"MsgID\":11223344,\"MsgTitle\":\"黑黑\",\"intList\":[3333],\"subObj\":{\"SubMsgID\":0,\"SubMsgTitle\":\"dddd\"},\"testList\":[\"aaaa\",\"bbbb\"],\"testListSpecial\":[{\"SubMsgID\":2,\"SubMsgTitle\":\"333\"},{\"SubMsgID\":3,\"SubMsgTitle\":\"4444\"}]}";  
	CTestStruct stru;  
	stru.DeSerialize(pstr);  
	CString strShow = "";  
	strShow.Format("objlist Size:%d\r\nlistIntCount:%d\r\nMsgID:%I64u\r\nMsgTile:%s\r\nMsgContent:%s\r\nSubMsgTitle:%s\r\nfirst value:%d",
		stru.testListSpecial.size(), stru.intList.size(), stru.MsgID, stru.MsgTitle.c_str(), stru.MsgContent.c_str(), stru.subObj.SubMsgTitle.c_str(),
		stru.intList.size() > 0 ? stru.intList[0] : 0);  
	AfxMessageBox(strShow);
打印结果:

objlist Size:2
listIntCount:1
MsgID:11223344
MsgTile:黑黑
MsgContent:哈哈
SubMsgTitle:dddd
first value:3333
目前仅支持vector与list类型的列表,对于其他特殊的列表类型,需要在子类中重载如下函数:

virtual Json::Value DoSpecialArraySerialize(const string& propertyName){ return "";}

至此,对于C++对象以及相关列表的序列化与反序列化均已支持,在此将源码贴出:

#ifndef CJSONOBJECTBASE_H
#define CJSONOBJECTBASE_H
#include <string>  
#include <vector>  
#include <list>
#include "json/json.h"  
using std::string;  
using std::vector;  
using std::list;

#pragma warning(disable:4267)

#define DoArrayDeSerialize_Wrapper(listType, type)\
	DoArrayDeSerialize<##listType<##type>, ##type>

#define Type_Wrapper(listType, type)\
	(##listType<##type>*)

#define DoArraySerialize_Wrapper(listType, type)\
	DoArraySerialize(Type_Wrapper(listType, type)addr);

#define DoObjArrayDeSerialize_Wrapper(listType, type)\
	DoObjArrayDeSerialize<##listType<type>>

typedef void* (*GenerateJsonObjForDeSerializeFromOutSide)(const string& propertyName);

struct CJsonObjectBase  
{  
protected:  
	enum CEnumJsonTypeMap  
	{
		asBool = 1,  
		asInt,  
		asUInt,  
		asString,  
		asInt64,  
		asUInt64,  
		asJsonObj,
		asSpecialArray,
		asVectorArray,
		asListArray,
	};  
public:  
	CJsonObjectBase(void){}  
public:  
	virtual ~CJsonObjectBase(void){		
	}  
	string Serialize()  
	{  
		Json::Value new_item = DoSerialize();         
		Json::FastWriter writer;    
		std::string out2 = writer.write(new_item);   
		return out2;  
	}  
	
	bool DeSerialize(const char* str)  
	{  
		Json::Reader reader;    
		Json::Value root;  
		if (reader.parse(str, root))  
		{    
			return DoDeSerialize(root);  
		}  
		return false;  
	}  

	Json::Value DoSerialize()  
	{  
		Json::Value new_item;  
		int nSize = m_vectorName.size();  
		for (int i=0; i < nSize; ++i )  
		{  
			void* pAddr = m_vectorPropertyAddr[i];  
			switch(m_vectorType[i])  
			{  
			case asVectorArray:
			case asListArray:
				new_item[m_vectorName[i]] = DoArraySerialize(pAddr, m_vectorType[i], m_vectorListParamType[i]);
				break;
			case asSpecialArray:  
				new_item[m_vectorName[i]] = DoSpecialArraySerialize(m_vectorName[i]); 
				break;  
			case asJsonObj:  
				new_item[m_vectorName[i]] = ((CJsonObjectBase*)pAddr)->DoSerialize();  
				break;  
			case asBool:  
				new_item[m_vectorName[i]] = Serialize<bool>(pAddr); 
			case asInt:  
				new_item[m_vectorName[i]] = Serialize<INT>(pAddr); 
				break;  
			case asUInt:  
				new_item[m_vectorName[i]] = Serialize<UINT>(pAddr);  
				break;  
			case asInt64:  
				new_item[m_vectorName[i]] = Serialize<LONGLONG>(pAddr);  
				break;  
			case asUInt64:  
				new_item[m_vectorName[i]] = Serialize<ULONGLONG>(pAddr);  
				break;  
			case asString:  
				new_item[m_vectorName[i]] = Serialize<string>(pAddr);  
			default:  
				//我暂时只支持这几种类型,需要的可以自行添加
				break;  
			}         
		}  
		return new_item;  
	} 
protected:
	bool DoDeSerialize(Json::Value& root)  
	{  
		int nSize = m_vectorName.size();  
		for (int i=0; i < nSize; ++i )  
		{  
			void* pAddr = m_vectorPropertyAddr[i];  

			switch(m_vectorType[i])  
			{  
			case asListArray:
			case asVectorArray:
				{
					if (root.isNull() || root[m_vectorName[i]].isNull())
					{
						break;
					}
					DoArrayDeSerialize(m_vectorName[i], pAddr, root[m_vectorName[i]], m_vectorType[i], m_vectorListParamType[i]);
				}
				break;
			case asJsonObj:  
				{  
					if (!root[ m_vectorName[i] ].isNull())   
						((CJsonObjectBase*)pAddr)->DoDeSerialize(root[m_vectorName[i]]);  
				}                 
				break;  
			case asBool:  
				(*(bool*)pAddr) = root.get(m_vectorName[i], 0).asBool();  
				break;  
			case asInt:  
				(*(INT*)pAddr) = root.get(m_vectorName[i], 0).asInt();  
				break;  
			case asUInt:  
				(*(UINT*)pAddr) = root.get(m_vectorName[i], 0).asUInt();  
				break;  
			case asInt64:  
				(*(LONGLONG*)pAddr) = root.get(m_vectorName[i], 0).asInt64();  
				break;  
			case asUInt64:  
				(*(ULONGLONG*)pAddr) = root.get(m_vectorName[i], 0).asUInt64();  
				break;  
			case asString:  
				(*(string*)pAddr) = root.get(m_vectorName[i], "").asString();  
			default:  
				//我暂时只支持这几种类型,需要的可以自行添加   
				break;  
			}             
		}  
		return true;  
	}  
	 
	void SetProperty(string name, CEnumJsonTypeMap type, void* addr,  CEnumJsonTypeMap listParamType = asInt)  
	{  
		m_vectorName.push_back(name);  
		m_vectorPropertyAddr.push_back(addr);  
		m_vectorType.push_back(type);  
		m_vectorListParamType.push_back(listParamType);
	}  
	virtual void SetPropertys() = 0;  
	//有特殊对象需要序列化时,请重载此函数 
	virtual Json::Value DoSpecialArraySerialize(const string& propertyName){ return "";}

	//在反序列化时,如果对象中嵌套了列表,并且列表中容纳的内容是其他特殊对象时,需要重载此函数,new出真正的对象
	virtual CJsonObjectBase* GenerateJsonObjForDeSerialize(const string& propertyName){ return NULL;}

	bool DoArrayDeSerialize(const string& propertyName, void* addr, Json::Value& root, CEnumJsonTypeMap listType, CEnumJsonTypeMap paramType)
	{
		if (listType == asVectorArray)
		{
			switch(paramType)
			{ 
			case asJsonObj:  
				{  
					return DoObjArrayDeSerialize_Wrapper(vector, CJsonObjectBase*)(propertyName, addr, root);
				}                 
				break;  
			case asBool:  
				//无 
				break; 
			case asInt:  
				return DoArrayDeSerialize_Wrapper(vector, INT)(addr, root); 
			case asUInt:  
				return DoArrayDeSerialize_Wrapper(vector, UINT)(addr, root);   
			case asInt64:  
				return DoArrayDeSerialize_Wrapper(vector, LONGLONG)(addr, root);     
			case asUInt64:  
				return DoArrayDeSerialize_Wrapper(vector, ULONGLONG)(addr, root);     
			case asString:  
				return DoArrayDeSerialize_Wrapper(vector, string)(addr, root);       
			default:
				break;  
			}
		}
		else if(listType == asListArray)
		{
			switch(paramType)
			{ 
			case asJsonObj:  
				{
					return DoObjArrayDeSerialize_Wrapper(list, CJsonObjectBase*)(propertyName, addr, root);
				}                 
				break;  
			case asBool:  
				return DoArrayDeSerialize_Wrapper(list, bool)(addr, root);
			case asInt:  
				return DoArrayDeSerialize_Wrapper(list, INT)(addr, root); 
 			case asUInt:  
				return DoArrayDeSerialize_Wrapper(list, UINT)(addr, root);   
 			case asInt64:  
 				return DoArrayDeSerialize_Wrapper(list, LONGLONG)(addr, root);     
			case asUInt64:  
 				return DoArrayDeSerialize_Wrapper(list, ULONGLONG)(addr, root);     
			case asString:  
				return DoArrayDeSerialize_Wrapper(list, string)(addr, root);     
			default:
				break;  
			}
		}
		
		return true;
	}

	//特殊对象列表的反序列化
	template<typename T1>
	bool DoObjArrayDeSerialize(const string& propertyName, void* addr, Json::Value& node)
	{
		if (!node.isArray())
		{
			return false;
		}
		T1* pList = (T1*)addr;
		int size = node.size();
		for(int i = 0; i < size; ++i)
		{
			CJsonObjectBase* pNode = GenerateJsonObjForDeSerialize(propertyName);
			pNode->DoDeSerialize(node[i]);
			pList->push_back(pNode);
		}
		return true;
	}
public:
	//常见类型列表的反序列化 
	template <typename T1, typename T2>
	static bool DoArrayDeSerialize(void* addr, Json::Value& node)
	{
		if (!node.isArray())
		{
			return false;
		}
		T1* pList = (T1*)addr;
		int size = node.size();
		for(int i = 0; i < size; ++i)
			pList->push_back( DeSerialize<T2>(node[i]) );
		return true;
	}

	//特殊对象列表的反序列化
	template<typename T1>
	static bool DoObjArrayDeSerialize(const string& propertyName, void* addr, Json::Value& node, GenerateJsonObjForDeSerializeFromOutSide funGenerate)
	{
		if (!node.isArray())
		{
			return false;
		}
		T1* pList = (T1*)addr;
		int size = node.size();
		for(int i = 0; i < size; ++i)
		{
			CJsonObjectBase* pNode = (CJsonObjectBase*)funGenerate(propertyName);
			pNode->DoDeSerialize(node[i]);
			pList->push_back(pNode);
		}
		return true;
	}
protected:
	Json::Value DoArraySerialize(void* addr, CEnumJsonTypeMap listType, CEnumJsonTypeMap paramType)
	{
		if (listType == asVectorArray)
		{
			switch(paramType)
			{ 
			case asBool:  
				return "";
			case asJsonObj:
				return DoArraySerialize_Wrapper(vector, CJsonObjectBase*);
			case asInt:  
				return DoArraySerialize_Wrapper(vector, INT);
			case asUInt:  
				return DoArraySerialize_Wrapper(vector, UINT); 
			case asInt64:  
				return DoArraySerialize_Wrapper(vector, LONGLONG);   
			case asUInt64:  
				return DoArraySerialize_Wrapper(vector, ULONGLONG);  
			case asString:  
				return DoArraySerialize_Wrapper(vector, string);
			}
		}
		else 
		{
			switch(paramType)
			{ 
			case asBool:  
				return DoArraySerialize_Wrapper(list, bool);
			case asJsonObj:
				return DoArraySerialize_Wrapper(list, CJsonObjectBase*);
			case asInt:  
				return DoArraySerialize_Wrapper(list, INT);
			case asUInt:  
				return DoArraySerialize_Wrapper(list, UINT); 
			case asInt64:  
				return DoArraySerialize_Wrapper(list, LONGLONG);   
			case asUInt64:  
				return DoArraySerialize_Wrapper(list, ULONGLONG);  
			case asString:  
				return DoArraySerialize_Wrapper(list, string);
			}
		}
		return "";
	}
public:
	template <typename T1>
	static Json::Value DoArraySerialize(T1* pList)
	{
		Json::Value arrayValue;
		for (T1::iterator it = pList->begin(); it != pList->end(); ++ it)
		{
			arrayValue.append(*it);			
		}
		return arrayValue;
	}	
	
	template <>
	static Json::Value DoArraySerialize(vector<CJsonObjectBase*>* pList)
	{
		Json::Value arrayValue;
		for (vector<CJsonObjectBase*>::iterator it = pList->begin(); it != pList->end(); ++ it)
		{
			arrayValue.append((*it)->DoSerialize());			
		}
		return arrayValue;
	}

	template <>
	static Json::Value DoArraySerialize(list<CJsonObjectBase*>* pList)
	{
		Json::Value arrayValue;
		for (list<CJsonObjectBase*>::iterator it = pList->begin(); it != pList->end(); ++ it)
		{
			arrayValue.append((*it)->DoSerialize());			
		}
		return arrayValue;
	}
	static string JsonValueToString(Json::Value& tvalue)
	{
		Json::FastWriter writer;    
		return writer.write(tvalue);
	}
private:
	template <typename T>
	Json::Value Serialize(void* addr)
	{
		return (*(T*)addr);
	}

	template <typename T>
	static T DeSerialize(Json::Value& root)
	{
		return GetData<T>(root);
	}

	template <typename T>
	static T GetData(Json::Value& root)
	{
		T temp;
		return temp;
	}

	template <>
	static bool GetData(Json::Value& root)
	{
		return root.asBool();
	}

	template <>
	static INT GetData(Json::Value& root)
	{
		return root.asInt();
	}

	template <>
	static UINT GetData(Json::Value& root)
	{
		return root.asUInt();
	}
	template <>
	static LONGLONG GetData(Json::Value& root)
	{
		return root.asInt64();
	}
	template <>
	static ULONGLONG GetData(Json::Value& root)
	{
		return root.asUInt64();
	}
	template <>
	static string GetData(Json::Value& root)
	{
		return root.asString();
	}

private:  
	vector<string> m_vectorName;  
	vector<void*>  m_vectorPropertyAddr;  
	vector<CEnumJsonTypeMap>     m_vectorType;
	vector<CEnumJsonTypeMap>     m_vectorListParamType;
}; 
#endif

如果哪位有任何意见建议,敬请回复!
完整的测试程序及DEMO请见: http://download.csdn.net/detail/tragicguy/5649527



  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值