一:背景

作为一名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的序列化与反序列化基类

先看代码:

#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函数,将各个字段的属性进行设置即可。

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

要使对象具体相应功能,需要继承上述的基类,如下:

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

继承后,我们可以使用如下代码来进行测试

序列化:

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

结果:

反序列化:

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.       目前我对属性的映射采用的是vector顺序映射的方式,这样必需在子类中对每一个属性进行设置,是否有宏的策略可以使这部分工作更加轻松?

2.       目前只支持整型、64位整型及字符串类型,需要支持其他类型,可以在基类中添加映射即可。

3.       目前只支持单个简单对象[其属性均为简单类型]的序列化与反序列化,暂时未考虑如何支持复杂的,如内部包含其他的复杂对象、包含数组等情况。

完整代码请于如下链接下载:

http://download.csdn.net/detail/tragicguy/5630473

C++对象的JSON序列化与反序列化探索的更多相关文章

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

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

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

    本文是基本上一篇博文进行改进而成,上一篇请见: C++对象的JSON序列化与反序列化探索 此处就不多说了,直接上代码. 1. 序列化基类 #pragma once #include <strin ...

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

    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正 一:背景 作为一名C++开发人员,我始终很期待能够像C#与JAVA那样,可以省力的进行对象的序列化与反序列化,但到现在为止,还没有找 ...

  4. Json序列化与反序列化(对象与Json字符串的转换)--C#

    public class JsonHelper { #region Json序列化与反序列化 /// <summary> /// 将json转化为对象 /// (需要提前构造好结构一致的M ...

  5. DotNet的JSON序列化与反序列化

    JSON(JavaScript Object Notation)JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.在现在的通信中,较多的采用JSON数据格式,JSON有 ...

  6. Newtonsoft.Json 序列化和反序列化 时间格式

    From : http://www.cnblogs.com/litian/p/3870975.html 1.JSON序列化 string JsonStr= JsonConvert.SerializeO ...

  7. Net中JSON序列化和反序列化处理(日期时间特殊处理)

    0  缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...

  8. Newtonsoft.Json 序列化和反序列化 时间格式 [转]

    1.JSON序列化 string JsonStr= JsonConvert.SerializeObject(Entity); eg:   A a=new A(); a.Name="Elain ...

  9. C# JSON 序列化和反序列化——JavaScriptSerializer实现

    一. JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据.您无法访问序列化程序的此实例.但是,此类公开了公共 API.因此, ...

随机推荐

  1. Visio Premium 2010密钥+破解激活方法

    Visio Premium 2010密钥+破解激活方法: 在安装时能够使用下面密钥: GR24B-GC2XY-KRXRG-2TRJJ-4X7DC VWQ6G-37WBG-J7DJP-CY66Y-V27 ...

  2. C++ AfxBeginThread

    计算从1+2+3...+100000=? 关键点 CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, in ...

  3. Android开发 侧边滑动菜单栏SlidingMenu结合Fragment

    SlidingMenu是一个开源项目, https://github.com/jfeinstein10/SlidingMenu .功能是创建侧边滑动菜单栏,效果类似人人Android客户端,可点击按钮 ...

  4. SQL用法总结

    1.创建数据库语句 create table persons( 'id' INT NOT NULL AUTO_INCREMENT, ) NOT NULL, ) NOT NULL, PRIMARY KE ...

  5. Ruby on Rails Tutorial 第一章 之 搭建开发环境

    云端开发环境,Cloud9(https://ide.c9.io/).这个开发环境预先安装好了Rails开发所需要的大多数软件,包括Ruby.RubyGems和Git,需要自己安装Rails. 1.安装 ...

  6. 《Java程序员面试宝典》读书笔记1

    今天读书发现一个很有趣的问题 请问以下程序会输出什么? public   class   Test2   {  public   static   void   main(String[]   arg ...

  7. laraval框架之数据库不可不吐槽的坑

    最近做的项目一直在用laraval框架,有些地方确实很方便,但是有些方面实在是太坑了,就比如这次在数据库里,官方文档写的是 Take note that email is not a required ...

  8. Linux 学习笔记 查看文件内容诸多命令

    查看文件内容 1.查看文件统计信息 stat 提供文件系统上某个文件的所有状态信息 2.查看文件类型 file 用来查看文件类型 (该命令将文件分成3类:文本类型:可执行文件:数据文件) 如果你有从未 ...

  9. [转]oracle EBS 基础100问

    from:http://www.cnblogs.com/xiaoL/p/3593691.html  http://f.dataguru.cn/thread-51057-1-1.html 1001 OR ...

  10. TensorFlow安装与测试

    官网:http://tensorflow.org/安装步骤:1.sudo apt-get install python-pip python-dev python-virtualenv 2.virtu ...