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


    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正

        一:背景

        作为一名C++开发人员,我始终很期待能够像C#JAVA那样,可以省力的进行对象的序列化与反序列化,但到现在为止,还没有找到相对完美的处理方案。

        本文旨在抛砖引玉,期待有更好的处理方案;同时向大家追求帮助,处理本文中未处理的问题。 

        二:相干技术介绍

        本方案采取JsonCpp来做具体的JSON的读入与输出,再结合类成员变量的映射,终究实现对象的JSON序列化与反序列化。

        本文不再探讨如何使用JsonCpp,此处将作者在应用时发现的两处问题进行说明:

        1.       下载Jsoncpp,编译其lib,并且引用到项目中,发现有如下错误:

        错误1       fatal error C1083: Cannot open compiler generated file: '../../build/vs71/release/lib_jsonjson_writer.asm': No such file or directory       c:Documents and SettingsAdministratorjsoncpp-src-0.6.0-rc2jsoncpp-src-0.6.0-rc2srclib_jsonjson_writer.cpp

        错误2       fatal error LNK1257: 代码生成失败     JasonSerialize 

         

         可以通过在修改LIB库项目的属性处理,如下图[关闭汇编输出]

        序列化和对象

        2.      JSONCPP官网首页的下载版本是0.5.0,此版本不支撑Int64等类型,下载版本jsoncpp-src-0.6.0-rc2后便可支撑. 

        三:一个基于JsonCpp的序列化与反序列化基类

        先看代码:

    #pragma once
    #include <string>
    #include <vector>
    #include "json/json.h"
    using std::string;
    using std::vector;
    struct CJsonObejectBase
    {
    protected:
    	enum CEnumJsonTypeMap
    	{
    		asInt = 1,
    		asUInt,
    		asString,
    		asInt64,
    		asUInt64,
    	};
    public:
    	CJsonObejectBase(void){}
    public:
    	virtual ~CJsonObejectBase(void){}
    	string Serialize()
    	{
    		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 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;
    			}		
    		}
    		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))
    		{  
    			int nSize = m_listName.size();
    			for (int i=0; i < nSize; ++i )
    			{
    				void* pAddr = m_listPropertyAddr[i];
    
    				switch(m_listType[i])
    				{
    				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;
    		}
    		return false;
    	}
    protected:
    	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;
    	vector<string> m_listName;
    	vector<void*>  m_listPropertyAddr;
    	vector<CEnumJsonTypeMap>	   m_listType;
    };
        每日一道理
    爱,有的时候不须要山盟海誓的承诺,但她一定须要细致入微的关怀与问候;爱,有的时候不须要梁祝化蝶的悲壮,但她一定须要心有灵犀的默契与投合;爱,有的时候不须要雄飞雌从的追随,但她一定须要相濡以沫的支撑与理解。

        此类主要有三个函数:Serialize、DeSerialize及 SetPropertys、SetProperty,其中前两个函数主要是用来实现对象的序列化与反序列化;SetPropertys是一个纯虚函数,如果一个类须要具备序列化功能,只须要从此类继承,同时调用SetProperty函数,将各个字段的属性进行设置便可。  

        四:使用对象的序列化及反序列化功能

        要使对象具体相应功能,须要继承上述的基类,如下: 

    struct CTestStruct : public CJsonObejectBase
    {
    	CTestStruct()
    	{
    		SetPropertys();
    	}
    	ULONGLONG MsgID;
    	string MsgTitle;
    	string MsgContent;
    protected:
    	//子类须要实现此函数,并且将相应的映射关系进行设置 
    	virtual void SetPropertys()
    	{
    		SetProperty("MsgID", asUInt64, &MsgID);
    		SetProperty("MsgTitle", asString, &MsgTitle);
    		SetProperty("MsgContent", asString, &MsgContent);
    	}
    };

        继承后,我们可以使用如下代码来进行测试

        序列化: 

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

        结果:

        序列化和对象

        反序列化: 

    void CJasonSerializeDlg::OnBnClickedOk2()
    {
    	const char* pstr = "{"MsgContent":"哈哈22","MsgID":11111111111111111,"MsgTitle":"黑黑22"}";
    	CTestStruct stru;
    	stru.DeSerialize(pstr);
    	CString strShow = "";
    	strShow.Format("MsgID:%I64u
    MsgTile:%s
    MsgContent:%s", stru.MsgID, stru.MsgTitle.c_str(), stru.MsgContent.c_str());
    	AfxMessageBox(strShow);
    }

        结果:

        序列化和对象 

        五:未处理的问题

        1.       现在我对属性的映射采取的是vector次序映射的方式,这样必需在子类中对每个属性进行设置,是不是有宏的策略可以使这部分工作更加省力?

        2.       现在只支撑整型、64位整型及字符串类型,须要支撑其他类型,可以在基类中添加映射便可。

        3.       现在只支撑单个简略对象[其属性均为简略类型]的序列化与反序列化,暂时未斟酌如何支撑复杂的,如外部包括其他的复杂对象、包括数组等情况。 

        完整代码请于如下链接下载:

         http://download.csdn.net/detail/tragicguy/5630473

    文章结束给大家分享下程序员的一些笑话语录: 程序员的愿望
      有一天一个程序员见到了上帝.上帝: 小伙子,我可以满足你一个愿望.程序员: 我希望中国国家队能再次打进世界杯.
      上帝: 这个啊!这个不好办啊,你还说下一个吧!
      程序员: 那好!我的下一个愿望是每天都能休息6个小时以上.
      上帝: 还是让中国国家打进世界杯.

    --------------------------------- 原创文章 By
    序列化和对象
    ---------------------------------

  • 相关阅读:
    SDN第三次上机作业
    团队作业——Beta冲刺
    SDN第二次上机作业
    在mpvue中使用map如何避坑
    仿一个好玩的滑动效果
    乡音
    mpvue支持小程序的分包加载
    台风🌀和口腔溃疡
    记一次cocos项目的加载速度优化
    如何用ajax下载文件
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3150403.html
Copyright © 2020-2023  润新知