C++ 转换成 JSON

分享到:

经常有朋友问我如何将C++对象转换成JSON格式字符串。我的回答通常是CppCMS中的json::value. 我也写过一篇文章介绍该技术。

但是最近有些不同的想法。因为用到一个vector<shared_ptr<> > 数据结构,json::value不支持这个模板特化。同时也发现json::value的设计思想是将所有的c++对象存储在std::map中,然后再导出为json字符串。但是在我开发的和看到的很多web service开发中,将对象转换成json字符串,是非常频繁的。在esri,对象非常多,json格式巨大。如果每次都缓存到map中,显然过多的copy,内存和cpu都消耗过大。

我的一贯用法就是用流来拼接字符串。这种方法又有点傻。受json::value的设计采用模板特化和偏特化的启发。我自己也写了一个简单的jsoner类。方便了自己开发,现在拿出来。看看能不能方便别人。

先看调用代码:

vector<string> emails = user_manager::get_emails(user_id);
content.user_emails = jsoner<vector<string> >::to_json("emails", emails);
shared_ptr<displays> ds = user_manager::find_displays(user_id);
content.user_displays_addresses = jsoner<displays>::to_json("displays", *ds);
第一个例子:
第一代码从mongodb中读取用户所有的email地址,放到vector<string>容器中。第二行代码将之导出为固定格式的json字符串。这是第一个例子,简单但很常用。cppcms::json::value不支持,转换会失败。

 

第二个例子:

第三行代码找到用户所有拥有的设备(复数),displays内部拥有一个vector<shared_ptr<display> >成员变量,display就是一个显示设备,拥有一些属性。这个例子比较复杂,但是也很常用。良好的封装经常用复数类包装,将底层容器的类型对外部屏蔽,这里你不知道我用的是vector,以后我还可以换成list。

为了支持上面的调用代码,我的jsoner类设计了三个模板重载形式。

#ifndef __JSON_HELPER_H
#define __JSON_HELPER_H
#include <time.h>
#include <string>
#include <vector>
#include <sstream>
#include <boost/shared_ptr.hpp>
template<typename T>
class jsoner {
 public:
static std::string to_json (std::string const& name, T const& value) {
std::stringstream stream;
stream << "{\"" << name << "\":";
stream << value.to_json();
stream << "}";
return stream.str();
}
};
template<>
class jsoner<std::vector<std::string> > {
 public:
static std::string to_json (std::string const& name, std::vector<std::string> const & value) {
std::vector<std::string>::const_iterator itor, last = value.end();
std::stringstream stream;
stream << "{\"" << name << "\":[";
int i = 0;
for (itor = value.begin(); itor != last; ++itor) {
stream << "{";
stream << "\"index\":" << "\"" << i << "\",";
stream << "\"value\":" << "\"" << *itor << "\"";
stream << "}";
if(itor != last -1) {
	stream << ",";
}
++i;
}
stream << "]}";
return stream.str();
}
};
template<typename T>
class jsoner<std::vector<boost::shared_ptr<T> > > {
 public:
static std::string to_json (std::string const& name, std::vector<boost::shared_ptr<T> > const & value) {
typename std::vector<boost::shared_ptr<T> >::const_iterator itor, last = value.end();
std::stringstream stream;
stream << "{\"" << name << "\":[";
int i = 0;
for (itor = value.begin(); itor != last; ++itor) {
stream << "{";
stream << "\"index\":" << "\"" << i << "\",";
stream << "\"value\":" << (*itor)->to_json();
stream << "}";
if(itor != last -1) {
	stream << ",";
}
++i;
}
stream << "]}";
return stream.str();
}
};
#endif

第一种形式是最普通的,要求T类型必须拥有to_json成员函数。

第二种形式用于支持vector<string>,是模板特化。

第三种形式也是一种特化,但是支持vector<shared_ptr<T>>参数。

 

在我刚才的第二个例子调用代码中,找到的是第一种形式用于displays,displays的to_json函数代码如下:

string displays::to_json() const {
return jsoner<vector<shared_ptr<display> > >::to_json("addresses", values_);
}
它内部调用了第三种形式的特化。而这种形式又要求display类拥有成员函数to_json。

In short,如果你自己的类想要使用这几个模板,都必须实现自己的to_json函数。

 

参考这种思路,可以扩充到自己需要的stl容器,比如list等。


转自:http://blog.csdn.net/sheismylife/article/details/7958470

昵    称:
验证码:

相关文档:

  • C/C++学习工具 ZinjaI
    ZinjaI 是一个多平台的 C/C++ 集成开发环境,主要用在教室中学习 C/C++ 语言用的。...
  • Linux C 的工具包:JustKit
    JustKit 是一个简单易于使用的 Linux C 的工具包...
  • C++ 异常堆栈跟踪器libcsdbg 的可视化工具:jTracer
    jTracer 是 libcsdbg 的可视化工具。当 libcsdbg 为异常、线程创建一个堆栈跟踪,可配置通过 TCP/IP 来广播跟踪的数据。而 jTracer 捕获这些数据...
  • Node.js的C++移植版本 Node.native
    node.native 是 node.js 的一个 C++11 (aka C++0x) 的一个移植。...
  • GObjects 预处理器:GOB
    GObject Builder (GOB) 是一个用来轻松创建 GObjects (glib objects) 的简单预处理器。它读取 C 代码中的类描述文件并生成 .c 和 .h 的文件。可以让...
  • C/C++编译器 AsmJit
    C/C++编译器 AsmJit...
  • 一个C/C++开发工具IDE - Anjuta
    Anjuta是一个C/C++ IDE,它最大的特色是灵活,同时打开多个文件,内嵌代码级的调试器(调用gdb),应用程序向导(Application widzards)可以方...
  • java嵌入c,c++程序指南
    本文为在 32 位 Windows 平台上实现 Java 本地方法提供了实用的 示例、步骤和准则。本文中的示例使用 Sun Microsystems 公司创建的 Java Developmen...
  • JSONCPP介绍及使用
    JSON全称为JavaScript ObjectNotation,它是一种轻量级的数据交换格式,易于阅读、编写、解析。 jsoncpp是c++解析JSON串常用的解析库之一。其...
  • 多态在 Java 和 C++ 编程语言中的实现比较
    众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。C++...
  • 类似于Java Spring的C++依赖注入库:autumnframework
    Autumn Framework 项目是用C++实现依赖注入。它支持属性setter注入和构造器注入。它可以在多个平台上编译。它支持POCO(普通的C + +对象)并...
  • 纯Java 实现的 C 语言预处理器 - JCPP
    JCPP 是一个完整、兼容、独立的纯Java 实现的 C 语言预处理器,其目的是为了使用编写在 Java 中可使用的 C 风格编译器...
  • C语言的伪随机数发生器 gjrand
    gjrand 是一个C语言的伪随机数生成器。伪随机数的意思是在这个随机数并不保证是真正的随机,只适合一些对随机要求不是很高的场合,...
  • 通用LINUX C类库 jzlibs
    通用LINUX C类库。 包含双向链表、单向链表、向量、哈希表、红黑树等经典数据结构及其算法...
  • libjc - C语言事件驱动开发包
    libjc 是 C 语言的事件驱动开发框架。...
  • C语言日志、事务API libjio
    libjio是一个C库做日志,交易为导向的I/O它提供了一个类UNIX的文件操作功能(如打开,读取和写入) ,这是装在一个交易框架,以使文件...
  • Java 中嵌入c/c++
    Java Native Interface(JNI)是Java语言的本地编程接口,是J2SDK的一部分。在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能。...