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类。方便了自己开发,现在拿出来。看看能不能方便别人。

先看调用代码:

  1. vector<string> emails = user_manager::get_emails(user_id);  
  2. content.user_emails = jsoner<vector<string> >::to_json("emails", emails);  
  3. shared_ptr<displays> ds = user_manager::find_displays(user_id);  
  4. content.user_displays_addresses = jsoner<displays>::to_json("displays", *ds);  
    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类设计了三个模板重载形式。

  1. #ifndef __JSON_HELPER_H   
  2. #define __JSON_HELPER_H   
  3.   
  4. #include <time.h>   
  5. #include <string>   
  6. #include <vector>   
  7. #include <sstream>   
  8. #include <boost/shared_ptr.hpp>   
  9.   
  10. template<typename T>  
  11. class jsoner {  
  12.  public:  
  13.   static std::string to_json (std::string const& name, T const& value) {  
  14.     std::stringstream stream;  
  15.     stream << "{\"" << name << "\":";  
  16.     stream << value.to_json();  
  17.     stream << "}";  
  18.     return stream.str();  
  19.   }  
  20. };  
  21.   
  22. template<>  
  23. class jsoner<std::vector<std::string> > {  
  24.  public:  
  25.   static std::string to_json (std::string const& name, std::vector<std::string> const & value) {  
  26.     std::vector<std::string>::const_iterator itor, last = value.end();  
  27.     std::stringstream stream;  
  28.     stream << "{\"" << name << "\":[";  
  29.     int i = 0;  
  30.     for (itor = value.begin(); itor != last; ++itor) {  
  31.       stream << "{";  
  32.       stream << "\"index\":" << "\"" << i << "\",";  
  33.       stream << "\"value\":" << "\"" << *itor << "\"";  
  34.       stream << "}";  
  35.       if(itor != last -1) {  
  36.     stream << ",";  
  37.       }  
  38.       ++i;  
  39.     }  
  40.     stream << "]}";  
  41.     return stream.str();  
  42.   }  
  43.   
  44. };  
  45.   
  46. template<typename T>  
  47. class jsoner<std::vector<boost::shared_ptr<T> > > {  
  48.  public:  
  49.   static std::string to_json (std::string const& name, std::vector<boost::shared_ptr<T> > const & value) {  
  50.     typename std::vector<boost::shared_ptr<T> >::const_iterator itor, last = value.end();  
  51.     std::stringstream stream;  
  52.     stream << "{\"" << name << "\":[";  
  53.     int i = 0;  
  54.     for (itor = value.begin(); itor != last; ++itor) {  
  55.       stream << "{";  
  56.       stream << "\"index\":" << "\"" << i << "\",";  
  57.       stream << "\"value\":" << (*itor)->to_json();  
  58.       stream << "}";  
  59.       if(itor != last -1) {  
  60.     stream << ",";  
  61.       }  
  62.       ++i;  
  63.     }  
  64.     stream << "]}";  
  65.     return stream.str();  
  66.   }  
  67.   
  68. };  
  69.   
  70.   
  71. #endif  
#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函数代码如下:

  1. string displays::to_json() const {  
  2.   return jsoner<vector<shared_ptr<display> > >::to_json("addresses", values_);  
  3. }  
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值