本文是基本上一篇博文进行改进而成,上一篇请见:
此处就不多说了,直接上代码。
1. 序列化基类
#pragma once#include#include #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 m_listName; vector m_listPropertyAddr; vector 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. 接下来要解决的问题
当对象中存在数组或者列表时,我暂时还没想到好的办法处理,如果哪位有思路,还请赐教;如果对于此类序列化与反序列化有好的方法,也请指教!