新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正

一:背景

作为一名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

文章结束给大家分享下程序员的一些笑话语录: 程序员的愿望
  有一天一个程序员见到了上帝.上帝: 小伙子,我可以满足你一个愿望.程序员: 我希望中国国家队能再次打进世界杯.
  上帝: 这个啊!这个不好办啊,你还说下一个吧!
  程序员: 那好!我的下一个愿望是每天都能休息6个小时以上.
  上帝: 还是让中国国家打进世界杯.

---------------------------------
原创文章 By
序列化和对象
---------------------------------

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

  1. 小解系列-自关联对象.Net MVC中 json序列化循环引用问题

    自关联对象在实际开发中用的还是比较多,例如常见的树形菜单.本文是自己实际的一个小测试,可以解决循环引用对象的json序列化问题,文笔不好请多见谅,如有错误请指出,希望有更好的解决方案,一起进步. 构造 ...

  2. hibernate+spring mvc, 解决hibernate 对象懒加载 json序列化问题

    引用地址 在使用Spring MVC时,@ResponseBody 注解的方法返回一个有懒加载对象的时候出现了异常,以登录为例: @RequestMapping("login") ...

  3. .Net深入实战系列—JSON序列化那点事儿

    序 当前主流的序列化JSON字符串主要有两种方式:JavaScriptSerializer及Json.net(Nuget标识:Newtonsoft.Json).JavaScriptSerializer ...

  4. ASP.NET MVC4 json序列化器

    ASP.NET MVC4中调用WEB API的四个方法 2012年06月07日00:05 it168网站原创 作者:廖煜嵘 编辑:景保玉 我要评论(0) [IT168技术]当今的软件开发中,设计软件的 ...

  5. JSON序列化那点事儿

    JSON序列化那点事儿 序 当前主流的序列化JSON字符串主要有两种方式:JavaScriptSerializer及Json.net(Nuget标识:Newtonsoft.Json).JavaScri ...

  6. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  7. .Net深入实战系列—JSON序列化那点事儿

    序 当前主流的序列化JSON字符串主要有两种方式:JavaScriptSerializer及Json.net(Nuget标识:Newtonsoft.Json).JavaScriptSerializer ...

  8. Spring整合Redis&JSON序列化&Spring/Web项目部署相关

    几种JSON框架用法和效率对比: https://blog.csdn.net/sisyphus_z/article/details/53333925 https://blog.csdn.net/wei ...

  9. Json序列化对象

    之前都是用的二进制的序列化方法,是.net自带的,但是最常用到的还是Json序列化 (1)只需要调用 Newtonsoft.Json.dll 即可 public class JsonTools { / ...

  10. 转载C# 对象转Json序列化

    转载原地址:  http://www.cnblogs.com/plokmju/p/ObjectByJson.html JSON Json(JavaScript Object Notation) 是一种 ...

随机推荐

  1. 八位彻底改变App Store的iOS开发者

    我们与 app 交互的方式已经被一群聪明的开发者所完全改变,他们的共性是对 app 都有各自独到的见解.下面就是其中最顶尖的八位. Loren Brichter Tweeite 不是 iOS 上第一个 ...

  2. C# 如何以参数的形式调用.exe程序

    System.Diagnostics.Process.Start("程序的路径", "参数1 参数2");第一个参数是aaa.exe 的路径,第二个参数是用空格 ...

  3. UVA 10529-Dumb Bones(概率dp)

    题意: 给出放一个多米诺骨牌,向左向右倒的概率,求要放好n个骨牌,需要放置的骨牌的期望次数. 分析: 用到区间dp的思想,如果一个位置的左面右面骨牌都已放好,考虑,放中间的情况, dp[i]表示放好前 ...

  4. cocos2d anchor point 锚点解析

    anchor point 究竟是怎么回事? 之所以造成不容易理解的是因为我们平时看待一个图片是 以图片的中心点 这一个维度来决定图片的位置的.而在cocos2d中决定一个 图片的位置是由两个维度 一个 ...

  5. bzoj 1408 [Noi2002]Robot(欧拉函数)

    [题目链接]  http://www.lydsy.com/JudgeOnline/problem.php?id=1408 [题意] 求m的所有约数中,满足可以分解成(奇数个不同素数/偶数个不同素数/其 ...

  6. ini_set /ini_get函数功能-----PHP

    配置PHP环境时,我们记得最初的一步就是修改php.ini文件,但是当我们在虚拟机中运行脚本,或者是我们因为其他的原因没有修改php.ini的权限时,我们该怎么办? ini_set()函数提供了在脚本 ...

  7. 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇01:播放序列动画》

    1.播放序列动画 系列动画播放概述 2D游戏中的动画系统,不同于3D游戏.3D游戏中,角色美术资源不仅包含角色模型的,还包括角色的贴图和动作等,模型本身自带角色的动作动画效果.2D游戏中,角色美术资源 ...

  8. C# 字符串格式

    1.数字补零输出字符串 String.Format("{0:D6}",123); 2.字符串靠左输出6位 String.Format("{0,-6}",&quo ...

  9. SAE 合并图片

    $domain = 'picleader'; //图片库的域名 $stgurl = 'http://lemonluoxing-picleader.stor.sinaapp.com/'; //绝对路径 ...

  10. Java设计模式系列之适配器模式

    适配器模式的定义 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.(就类似于我们充电器的转接头将220V的电压转换成我们的手机端 ...