本文是基本上一篇博文進行改進而成,上一篇請見:
此處就不多說了,直接上代碼。
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\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. 接下來要解決的問題
當對象中存在數組或者列表時,我暫時還沒想到好的辦法處理,如果哪位有思路,還請賜教;如果對於此類序列化與反序列化有好的方法,也請指教!