在前两篇文章中,我们已经完成对普通对象以及复杂对象嵌套的序列化与反序列化,见如下地址:
C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化
经过一番折腾,总算把带有列表的对象的序列化完成了,目前支持 list 和 vector 的列表,以及自定义的其他类型的列表,我们可以先来看看实现的效果。
复杂对象及带列表对象的序列号主要有如下几种:
1. 普通的list列表,如:list<string>
list<string> testList;
testList.push_back("33333333");
testList.push_back("55555555");
tvalue = CJsonObjectBase::DoArraySerialize<list<string>>(&testList);
out = CJsonObjectBase::JsonValueToString(tvalue);
AfxMessageBox(out.c_str());
序列化结果为:
["33333333","55555555"]
2. 复杂对象的列表,如list<CTestStru*>
Json::Value tvalue;
std::string out;
vector<CSubTestStruct*> testListSpecial;
obj = new CSubTestStruct();
obj->SubMsgID = 2;
obj->SubMsgTitle = "333";
testListSpecial.push_back(obj);
obj = new CSubTestStruct();
obj->SubMsgID = 3;
obj->SubMsgTitle = "4444";
testListSpecial.push_back(obj);
tvalue = CJsonObjectBase::DoArraySerialize<vector<CJsonObjectBase*>>((vector<CJsonObjectBase*>*)&testListSpecial);
out = CJsonObjectBase::JsonValueToString(tvalue);
AfxMessageBox(out.c_str());
[{"SubMsgID":2,"SubMsgTitle":"333"},{"SubMsgID":3,"SubMsgTitle":"4444"}]
此注需要注意的是,使用完毕后,一定要记得销毁列表中的对象:
for (vector<CSubTestStruct*>::iterator it = testListSpecial.begin(); it != testListSpecial.end(); ++ it)
{
delete (*it);
}
反序列化:
void* GenerateTest(const string& name)
{
return new CSubTestStruct();
}
CString strTest = "";
string strTestEx = "[{\"SubMsgID\":2,\"SubMsgTitle\":\"2222\"},{\"SubMsgID\":4444,\"SubMsgTitle\":\"4444\"}]";
Json::Reader reader;
Json::Value root;
if (reader.parse(strTestEx, root))
{
vector<CSubTestStruct*> listObjTest;
CJsonObjectBase::DoObjArrayDeSerialize<vector<CJsonObjectBase*>>("test", &listObjTest, root, GenerateTest);
strTest.Format("count %d\r\nfirst subTitle:%s", listObjTest.size(), listObjTest.size() > 0 ? listObjTest[0]->SubMsgTitle.c_str() : "");
AfxMessageBox(strTest); for (vector<CSubTestStruct*>::iterator it = listObjTest.begin(); it != listObjTest.end(); ++ it)
{
delete (*it);
}
}
打印结果:
count 2
first subTitle:2222
3. 在对象中包含普通及复杂的列表,如下:
struct CSubTestStruct : public CJsonObjectBase
{
CSubTestStruct()
{
SubMsgID = 0;
SetPropertys();
} ULONGLONG SubMsgID;
string SubMsgTitle;
protected:
//子类需要实现此函数,并且将相应的映射关系进行设置
virtual void SetPropertys()
{
SetProperty("SubMsgID", asUInt64, &SubMsgID);
SetProperty("SubMsgTitle", asString, &SubMsgTitle);
}
};
struct CTestStruct : public CJsonObjectBase
{
CTestStruct()
{
SetPropertys();
}
~CTestStruct()
{
for (vector<CSubTestStruct*>::iterator it = testListSpecial.begin(); it != testListSpecial.end(); ++ it)
{
delete (*it);
}
}
ULONGLONG MsgID;
string MsgTitle;
string MsgContent;
CSubTestStruct subObj;
vector<INT> intList;
list<string> testList;
vector<CSubTestStruct*> testListSpecial;
protected:
CJsonObjectBase* GenerateJsonObjForDeSerialize(const string& propertyName)
{
if("testListSpecial" == propertyName)
{
return new CSubTestStruct();
}
return NULL;
}
//子类需要实现此函数,并且将相应的映射关系进行设置
virtual void SetPropertys()
{
SetProperty("MsgID", asUInt64, &MsgID);
SetProperty("MsgTitle", asString, &MsgTitle);
SetProperty("MsgContent", asString, &MsgContent);
SetProperty("subObj", asJsonObj, &subObj);
SetProperty("intList", asVectorArray, &intList);
SetProperty("testList", asListArray, &testList, asString);
SetProperty("testListSpecial", asVectorArray, &testListSpecial, asJsonObj);
}
};
序列化代码:
CTestStruct stru;
stru.MsgID = 11223344;
stru.MsgTitle = "黑黑";
stru.MsgContent = "哈哈";
stru.testList.push_back("aaaa");
stru.testList.push_back("bbbb");
stru.intList.push_back(3333);
CSubTestStruct* obj = new CSubTestStruct();
obj->SubMsgID = 2;
obj->SubMsgTitle = "333";
stru.testListSpecial.push_back(obj);
obj = new CSubTestStruct();
obj->SubMsgID = 3;
obj->SubMsgTitle = "4444";
stru.testListSpecial.push_back(obj);
CString strTest = stru.Serialize().c_str();
AfxMessageBox(strTest);
打印结果:
{"MsgContent":"哈哈","MsgID":11223344,"MsgTitle":"黑黑","intList":[3333],"subObj":{"SubMsgID":0,"SubMsgTitle":""},"testList":["aaaa","bbbb"],"testListSpecial":[{"SubMsgID":2,"SubMsgTitle":"333"},{"SubMsgID":3,"SubMsgTitle":"4444"}]}
反序列化代码:
const char* pstr = "{\"MsgContent\":\"哈哈\",\"MsgID\":11223344,\"MsgTitle\":\"黑黑\",\"intList\":[3333],\"subObj\":{\"SubMsgID\":0,\"SubMsgTitle\":\"dddd\"},\"testList\":[\"aaaa\",\"bbbb\"],\"testListSpecial\":[{\"SubMsgID\":2,\"SubMsgTitle\":\"333\"},{\"SubMsgID\":3,\"SubMsgTitle\":\"4444\"}]}";
CTestStruct stru;
stru.DeSerialize(pstr);
CString strShow = "";
strShow.Format("objlist Size:%d\r\nlistIntCount:%d\r\nMsgID:%I64u\r\nMsgTile:%s\r\nMsgContent:%s\r\nSubMsgTitle:%s\r\nfirst value:%d",
stru.testListSpecial.size(), stru.intList.size(), stru.MsgID, stru.MsgTitle.c_str(), stru.MsgContent.c_str(), stru.subObj.SubMsgTitle.c_str(),
stru.intList.size() > 0 ? stru.intList[0] : 0);
AfxMessageBox(strShow);
打印结果:
objlist Size:2
listIntCount:1
MsgID:11223344
MsgTile:黑黑
MsgContent:哈哈
SubMsgTitle:dddd
first value:3333
目前仅支持vector与list类型的列表,对于其他特殊的列表类型,需要在子类中重载如下函数:
virtual Json::Value DoSpecialArraySerialize(const string& propertyName){ return "";}
至此,对于C++对象以及相关列表的序列化与反序列化均已支持,在此将源码贴出:
#ifndef CJSONOBJECTBASE_H
#define CJSONOBJECTBASE_H
#include <string>
#include <vector>
#include <list>
#include "json/json.h"
using std::string;
using std::vector;
using std::list; #pragma warning(disable:4267) #define DoArrayDeSerialize_Wrapper(listType, type)\
DoArrayDeSerialize<##listType<##type>, ##type> #define Type_Wrapper(listType, type)\
(##listType<##type>*) #define DoArraySerialize_Wrapper(listType, type)\
DoArraySerialize(Type_Wrapper(listType, type)addr); #define DoObjArrayDeSerialize_Wrapper(listType, type)\
DoObjArrayDeSerialize<##listType<type>> typedef void* (*GenerateJsonObjForDeSerializeFromOutSide)(const string& propertyName); struct CJsonObjectBase
{
protected:
enum CEnumJsonTypeMap
{
asBool = 1,
asInt,
asUInt,
asString,
asInt64,
asUInt64,
asJsonObj,
asSpecialArray,
asVectorArray,
asListArray,
};
public:
CJsonObjectBase(void){}
public:
virtual ~CJsonObjectBase(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;
} Json::Value DoSerialize()
{
Json::Value new_item;
int nSize = m_vectorName.size();
for (int i=0; i < nSize; ++i )
{
void* pAddr = m_vectorPropertyAddr[i];
switch(m_vectorType[i])
{
case asVectorArray:
case asListArray:
new_item[m_vectorName[i]] = DoArraySerialize(pAddr, m_vectorType[i], m_vectorListParamType[i]);
break;
case asSpecialArray:
new_item[m_vectorName[i]] = DoSpecialArraySerialize(m_vectorName[i]);
break;
case asJsonObj:
new_item[m_vectorName[i]] = ((CJsonObjectBase*)pAddr)->DoSerialize();
break;
case asBool:
new_item[m_vectorName[i]] = Serialize<bool>(pAddr);
case asInt:
new_item[m_vectorName[i]] = Serialize<INT>(pAddr);
break;
case asUInt:
new_item[m_vectorName[i]] = Serialize<UINT>(pAddr);
break;
case asInt64:
new_item[m_vectorName[i]] = Serialize<LONGLONG>(pAddr);
break;
case asUInt64:
new_item[m_vectorName[i]] = Serialize<ULONGLONG>(pAddr);
break;
case asString:
new_item[m_vectorName[i]] = Serialize<string>(pAddr);
default:
//我暂时只支持这几种类型,需要的可以自行添加
break;
}
}
return new_item;
}
protected:
bool DoDeSerialize(Json::Value& root)
{
int nSize = m_vectorName.size();
for (int i=0; i < nSize; ++i )
{
void* pAddr = m_vectorPropertyAddr[i]; switch(m_vectorType[i])
{
case asListArray:
case asVectorArray:
{
if (root.isNull() || root[m_vectorName[i]].isNull())
{
break;
}
DoArrayDeSerialize(m_vectorName[i], pAddr, root[m_vectorName[i]], m_vectorType[i], m_vectorListParamType[i]);
}
break;
case asJsonObj:
{
if (!root[ m_vectorName[i] ].isNull())
((CJsonObjectBase*)pAddr)->DoDeSerialize(root[m_vectorName[i]]);
}
break;
case asBool:
(*(bool*)pAddr) = root.get(m_vectorName[i], 0).asBool();
break;
case asInt:
(*(INT*)pAddr) = root.get(m_vectorName[i], 0).asInt();
break;
case asUInt:
(*(UINT*)pAddr) = root.get(m_vectorName[i], 0).asUInt();
break;
case asInt64:
(*(LONGLONG*)pAddr) = root.get(m_vectorName[i], 0).asInt64();
break;
case asUInt64:
(*(ULONGLONG*)pAddr) = root.get(m_vectorName[i], 0).asUInt64();
break;
case asString:
(*(string*)pAddr) = root.get(m_vectorName[i], "").asString();
default:
//我暂时只支持这几种类型,需要的可以自行添加
break;
}
}
return true;
} void SetProperty(string name, CEnumJsonTypeMap type, void* addr, CEnumJsonTypeMap listParamType = asInt)
{
m_vectorName.push_back(name);
m_vectorPropertyAddr.push_back(addr);
m_vectorType.push_back(type);
m_vectorListParamType.push_back(listParamType);
}
virtual void SetPropertys() = 0;
//有特殊对象需要序列化时,请重载此函数
virtual Json::Value DoSpecialArraySerialize(const string& propertyName){ return "";} //在反序列化时,如果对象中嵌套了列表,并且列表中容纳的内容是其他特殊对象时,需要重载此函数,new出真正的对象
virtual CJsonObjectBase* GenerateJsonObjForDeSerialize(const string& propertyName){ return NULL;} bool DoArrayDeSerialize(const string& propertyName, void* addr, Json::Value& root, CEnumJsonTypeMap listType, CEnumJsonTypeMap paramType)
{
if (listType == asVectorArray)
{
switch(paramType)
{
case asJsonObj:
{
return DoObjArrayDeSerialize_Wrapper(vector, CJsonObjectBase*)(propertyName, addr, root);
}
break;
case asBool:
//无
break;
case asInt:
return DoArrayDeSerialize_Wrapper(vector, INT)(addr, root);
case asUInt:
return DoArrayDeSerialize_Wrapper(vector, UINT)(addr, root);
case asInt64:
return DoArrayDeSerialize_Wrapper(vector, LONGLONG)(addr, root);
case asUInt64:
return DoArrayDeSerialize_Wrapper(vector, ULONGLONG)(addr, root);
case asString:
return DoArrayDeSerialize_Wrapper(vector, string)(addr, root);
default:
break;
}
}
else if(listType == asListArray)
{
switch(paramType)
{
case asJsonObj:
{
return DoObjArrayDeSerialize_Wrapper(list, CJsonObjectBase*)(propertyName, addr, root);
}
break;
case asBool:
return DoArrayDeSerialize_Wrapper(list, bool)(addr, root);
case asInt:
return DoArrayDeSerialize_Wrapper(list, INT)(addr, root);
case asUInt:
return DoArrayDeSerialize_Wrapper(list, UINT)(addr, root);
case asInt64:
return DoArrayDeSerialize_Wrapper(list, LONGLONG)(addr, root);
case asUInt64:
return DoArrayDeSerialize_Wrapper(list, ULONGLONG)(addr, root);
case asString:
return DoArrayDeSerialize_Wrapper(list, string)(addr, root);
default:
break;
}
} return true;
} //特殊对象列表的反序列化
template<typename T1>
bool DoObjArrayDeSerialize(const string& propertyName, void* addr, Json::Value& node)
{
if (!node.isArray())
{
return false;
}
T1* pList = (T1*)addr;
int size = node.size();
for(int i = 0; i < size; ++i)
{
CJsonObjectBase* pNode = GenerateJsonObjForDeSerialize(propertyName);
pNode->DoDeSerialize(node[i]);
pList->push_back(pNode);
}
return true;
}
public:
//常见类型列表的反序列化
template <typename T1, typename T2>
static bool DoArrayDeSerialize(void* addr, Json::Value& node)
{
if (!node.isArray())
{
return false;
}
T1* pList = (T1*)addr;
int size = node.size();
for(int i = 0; i < size; ++i)
pList->push_back( DeSerialize<T2>(node[i]) );
return true;
} //特殊对象列表的反序列化
template<typename T1>
static bool DoObjArrayDeSerialize(const string& propertyName, void* addr, Json::Value& node, GenerateJsonObjForDeSerializeFromOutSide funGenerate)
{
if (!node.isArray())
{
return false;
}
T1* pList = (T1*)addr;
int size = node.size();
for(int i = 0; i < size; ++i)
{
CJsonObjectBase* pNode = (CJsonObjectBase*)funGenerate(propertyName);
pNode->DoDeSerialize(node[i]);
pList->push_back(pNode);
}
return true;
}
protected:
Json::Value DoArraySerialize(void* addr, CEnumJsonTypeMap listType, CEnumJsonTypeMap paramType)
{
if (listType == asVectorArray)
{
switch(paramType)
{
case asBool:
return "";
case asJsonObj:
return DoArraySerialize_Wrapper(vector, CJsonObjectBase*);
case asInt:
return DoArraySerialize_Wrapper(vector, INT);
case asUInt:
return DoArraySerialize_Wrapper(vector, UINT);
case asInt64:
return DoArraySerialize_Wrapper(vector, LONGLONG);
case asUInt64:
return DoArraySerialize_Wrapper(vector, ULONGLONG);
case asString:
return DoArraySerialize_Wrapper(vector, string);
}
}
else
{
switch(paramType)
{
case asBool:
return DoArraySerialize_Wrapper(list, bool);
case asJsonObj:
return DoArraySerialize_Wrapper(list, CJsonObjectBase*);
case asInt:
return DoArraySerialize_Wrapper(list, INT);
case asUInt:
return DoArraySerialize_Wrapper(list, UINT);
case asInt64:
return DoArraySerialize_Wrapper(list, LONGLONG);
case asUInt64:
return DoArraySerialize_Wrapper(list, ULONGLONG);
case asString:
return DoArraySerialize_Wrapper(list, string);
}
}
return "";
}
public:
template <typename T1>
static Json::Value DoArraySerialize(T1* pList)
{
Json::Value arrayValue;
for (T1::iterator it = pList->begin(); it != pList->end(); ++ it)
{
arrayValue.append(*it);
}
return arrayValue;
} template <>
static Json::Value DoArraySerialize(vector<CJsonObjectBase*>* pList)
{
Json::Value arrayValue;
for (vector<CJsonObjectBase*>::iterator it = pList->begin(); it != pList->end(); ++ it)
{
arrayValue.append((*it)->DoSerialize());
}
return arrayValue;
} template <>
static Json::Value DoArraySerialize(list<CJsonObjectBase*>* pList)
{
Json::Value arrayValue;
for (list<CJsonObjectBase*>::iterator it = pList->begin(); it != pList->end(); ++ it)
{
arrayValue.append((*it)->DoSerialize());
}
return arrayValue;
}
static string JsonValueToString(Json::Value& tvalue)
{
Json::FastWriter writer;
return writer.write(tvalue);
}
private:
template <typename T>
Json::Value Serialize(void* addr)
{
return (*(T*)addr);
} template <typename T>
static T DeSerialize(Json::Value& root)
{
return GetData<T>(root);
} template <typename T>
static T GetData(Json::Value& root)
{
T temp;
return temp;
} template <>
static bool GetData(Json::Value& root)
{
return root.asBool();
} template <>
static INT GetData(Json::Value& root)
{
return root.asInt();
} template <>
static UINT GetData(Json::Value& root)
{
return root.asUInt();
}
template <>
static LONGLONG GetData(Json::Value& root)
{
return root.asInt64();
}
template <>
static ULONGLONG GetData(Json::Value& root)
{
return root.asUInt64();
}
template <>
static string GetData(Json::Value& root)
{
return root.asString();
} private:
vector<string> m_vectorName;
vector<void*> m_vectorPropertyAddr;
vector<CEnumJsonTypeMap> m_vectorType;
vector<CEnumJsonTypeMap> m_vectorListParamType;
};
#endif
如果哪位有任何意见建议,敬请回复!
完整的测试程序及DEMO请见:http://download.csdn.net/detail/tragicguy/5649527