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
MsgTile:%s
MsgContent:%s
SubMsgTitle:%s", stru.MsgID, stru.MsgTitle.c_str(), stru.MsgContent.c_str(), stru.subObj.SubMsgTitle.c_str());
	AfxMessageBox(strShow);
}

效果

4. 接下来要解决的问题

当对象中存在数组或者列表时,我暂时还没想到好的办法处理,如果哪位有思路,还请赐教;如果对于此类序列化与反序列化有好的方法,也请指教!


原文地址:https://www.cnblogs.com/snake-hand/p/3151270.html