C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化

时间:2021-04-21 19:27:14

本文是基本上一篇博文进行改进而成,上一篇请见:

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);
}

效果

C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化

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);
}

效果

C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化

4. 接下来要解决的问题

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