程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++對象的JSON序列化與反序列化探索

C++對象的JSON序列化與反序列化探索

編輯:C++入門知識

一:背景

作為一名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的序列化與反序列化基類

先看代碼:

[cpp] v #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; 
}; 

#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函數,將各個字段的屬性進行設置即可。 

四:使用對象的序列化及反序列化功能

要使對象具體相應功能,需要繼承上述的基類,如下:

[cpp]  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); 
    } 
}; 

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);
 }
};繼承後,我們可以使用如下代碼來進行測試

序列化:

[cpp] void CJasonSerializeDlg::OnBnClickedOk() 

    CTestStruct stru; 
    stru.MsgID = 11223344; 
    stru.MsgTitle = "黑黑"; 
    stru.MsgContent = "哈哈"; 
    CString strTest = stru.Serialize().c_str(); 
    AfxMessageBox(strTest); 

void CJasonSerializeDlg::OnBnClickedOk()
{
 CTestStruct stru;
 stru.MsgID = 11223344;
 stru.MsgTitle = "黑黑";
 stru.MsgContent = "哈哈";
 CString strTest = stru.Serialize().c_str();
 AfxMessageBox(strTest);
 

 


反序列化:

[cpp] 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. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved