序列化对象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_json\json_writer.asm': No such file or directory?????? c:\Documents and Settings\Administrator\jsoncpp-src-0.6.0-rc2\jsoncpp-src-0.6.0-rc2\src\lib_json\json_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\r\nMsgTile:%s\r\nMsgContent:%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
序列化和對象
---------------------------------
轉載于:https://www.cnblogs.com/xinyuyuanm/p/3150403.html
總結
以上是生活随笔為你收集整理的序列化对象C++对象的JSON序列化与反序列化探索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《c陷阱与缺陷》笔记--注意边界值
- 下一篇: MVC3 中使用Unity实现依赖注入