C++對象的JSON序列化與反序列化探索續-複雜對象的序列化與反序列化

本文是基本上一篇博文進行改進而成,上一篇請見:

C++對象的JSON序列化與反序列化探索

此處就不多說了,直接上代碼。

1. 序列化基類

#pragma once
#include <string>
#include <vector>
#include "json/json.h"
using std::string;
using std::vector;
struct CJsonObejectBase
{
protected:
	enum CEnumJsonTypeMap
	{
		asArray = 1,	//是數組
		asJsonObj,		//是複雜對象
		asBool,
		asInt,
		asUInt,
		asString,
		asInt64,
		asUInt64,
	};
public:
	CJsonObejectBase(void){}
public:
	virtual ~CJsonObejectBase(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;
	}
protected:
	bool DoDeSerialize(Json::Value& root)
	{
		int nSize = m_listName.size();
		for (int i=0; i < nSize; ++i )
		{
			void* pAddr = m_listPropertyAddr[i];

			switch(m_listType[i])
			{
			case asJsonObj:
				{
					if (!root[ m_listName[i] ].isNull()) 
						((CJsonObejectBase*)pAddr)->DoDeSerialize(root[m_listName[i]]);
				}				
				break;
			case asBool:
				(*(bool*)pAddr) = root.get(m_listName[i], 0).asBool();
				break;
			case asInt:
				(*(INT*)pAddr) = root.get(m_listName[i], 0).asInt();
				break;
			case asUInt:
				(*(UINT*)pAddr) = root.get(m_listName[i], 0).asUInt();
				break;
			case asInt64:
				(*(LONGLONG*)pAddr) = root.get(m_listName[i], 0).asInt64();
				break;
			case asUInt64:
				(*(ULONGLONG*)pAddr) = root.get(m_listName[i], 0).asUInt64();
				break;
			case asString:
				(*(string*)pAddr) = root.get(m_listName[i], "").asString();
			default:
				//我暫時只支持這幾種類型,需要的可以自行添加 
				break;
			}			
		}
		return true;
	}

	Json::Value DoSerialize()
	{
		Json::Value new_item;
		int nSize = m_listName.size();
		for (int i=0; i < nSize; ++i )
		{
			void* pAddr = m_listPropertyAddr[i];
			switch(m_listType[i])
			{
			case asArray:

				break;
			case asJsonObj:
				new_item[m_listName[i]] = ((CJsonObejectBase*)pAddr)->DoSerialize();
				break;
			case asBool:
				new_item[m_listName[i]] = (*(bool*)pAddr);
			case asInt:
				new_item[m_listName[i]] = (*(INT*)pAddr);
				break;
			case asUInt:
				new_item[m_listName[i]] = (*(UINT*)pAddr);
				break;
			case asInt64:
				new_item[m_listName[i]] = (*(LONGLONG*)pAddr);
				break;
			case asUInt64:
				new_item[m_listName[i]] = (*(ULONGLONG*)pAddr);
				break;
			case asString:
				new_item[m_listName[i]] = (*(string*)pAddr);
			default:
				//我暫時只支持這幾種類型,需要的可以自行添加 
				break;
			}		
		}
		return new_item;
	}
	void SetProperty(string name, CEnumJsonTypeMap type, void* addr)
	{
		m_listName.push_back(name);
		m_listPropertyAddr.push_back(addr);
		m_listType.push_back(type);
	}
	virtual void SetPropertys() = 0;

private:
	vector<string> m_listName;
	vector<void*>  m_listPropertyAddr;
	vector<CEnumJsonTypeMap>	   m_listType;
};
2.測試的派生類

struct CSubTestStruct : public CJsonObejectBase
{
	CSubTestStruct()
	{
		SubMsgID = 0;
		SetPropertys();
	}
	ULONGLONG SubMsgID;
	string SubMsgTitle;
protected:
	//子類需要實現此函數,並且將相應的映射關係進行設置 
	virtual void SetPropertys()
	{
		SetProperty("SubMsgID", asUInt64, &SubMsgID);
		SetProperty("SubMsgTitle", asString, &SubMsgTitle);
	}
};
struct CTestStruct : public CJsonObejectBase
{
	CTestStruct()
	{
		SetPropertys();
	}
	ULONGLONG MsgID;
	string MsgTitle;
	string MsgContent;
	CSubTestStruct subObj;
protected:
	//子類需要實現此函數,並且將相應的映射關係進行設置 
	virtual void SetPropertys()
	{
		SetProperty("MsgID", asUInt64, &MsgID);
		SetProperty("MsgTitle", asString, &MsgTitle);
		SetProperty("MsgContent", asString, &MsgContent);
		SetProperty("subObj", asJsonObj, &subObj);
	}
};

注意,此處CSubTestStruct類型的對象是CTestStruct的一個成員.

3.測試代碼及效果圖

1). 序列化

void CJasonSerializeDlg::OnBnClickedOk()
{
	CTestStruct stru;
	stru.MsgID = 11223344;
	stru.MsgTitle = "黑黑";
	stru.MsgContent = "哈哈";
	CString strTest = stru.Serialize().c_str();
	AfxMessageBox(strTest);
}
效果

2). 反序列化

void CJasonSerializeDlg::OnBnClickedOk2()
{
	const char* pstr = "{\"MsgContent\":\"哈哈22\",\"MsgID\":11111,\"MsgTitle\":\"黑黑22\",\"subObj\":{\"SubMsgID\":3333,\"SubMsgTitle\":\"子內容\"}}";
	CTestStruct stru;
	stru.DeSerialize(pstr);
	CString strShow = "";
	strShow.Format("MsgID:%I64u\r\nMsgTile:%s\r\nMsgContent:%s\r\nSubMsgTitle:%s", stru.MsgID, stru.MsgTitle.c_str(), stru.MsgContent.c_str(), stru.subObj.SubMsgTitle.c_str());
	AfxMessageBox(strShow);
}
效果

4. 接下來要解決的問題

當對象中存在數組或者列表時,我暫時還沒想到好的辦法處理,如果哪位有思路,還請賜教;如果對於此類序列化與反序列化有好的方法,也請指教!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章