C++对象的JSON序列化与反序列化探索完结-列表的序列化与反序列化

来源:互联网 发布:java 二叉树容器 编辑:程序博客网 时间:2024/05/15 17:13

在前两篇文章中,我们已经完成对普通对象以及复杂对象嵌套的序列化与反序列化,见如下地址:

C++对象的JSON序列化与反序列化探索

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 2first 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:2listIntCount:1MsgID:11223344MsgTile:黑黑MsgContent:哈哈SubMsgTitle:ddddfirst 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



原创粉丝点击