zoukankan      html  css  js  c++  java
  • 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. 接下来要解决的问题

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


  • 相关阅读:
    Vue 页面权限控制和登陆验证
    Vue 动态添加路由及生成菜单
    开发一个简单的 Vue 弹窗组件
    VS使用和错误收集
    ARP欺骗的实现
    虚拟机安装64位系统(Windows Server 2008R2 Datacenter版本)
    Kali安装问题
    HTML5学习之四:多媒体播放
    HTML5学习之三:文件与拖放
    HTML5学习之二:HTML5中的表单2
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3151270.html
Copyright © 2011-2022 走看看