00001 #ifndef _BOOST_RPC_JSON_HPP_
00002 #define _BOOST_RPC_JSON_HPP_
00003 #include <boost/reflect/reflect.hpp>
00004
00005 #include <boost/rpc/varint.hpp>
00006 #include <boost/rpc/required.hpp>
00007 #include <boost/rpc/errors.hpp>
00008 #include <boost/cmt/log/log.hpp>
00009 #include <boost/rpc/base64.hpp>
00010 #include <sstream>
00011 #include <iostream>
00012 #include <map>
00013 #include <iomanip>
00014
00015 #include <boost/fusion/container/vector.hpp>
00016 #include <boost/fusion/algorithm.hpp>
00017 #include <boost/fusion/support/is_sequence.hpp>
00018 #include <boost/fusion/sequence/intrinsic/size.hpp>
00019 #include <boost/json/value.hpp>
00020 #include <boost/json/writer.hpp>
00021 #include <boost/json/reader.hpp>
00022
00023 namespace boost { namespace rpc { namespace json {
00024
00025 template<typename T>
00026 void pack( boost::json::Value& jsv, const T& v );
00027 template<typename T>
00028 void unpack( const boost::json::Value& jsv, T& v );
00029 void pack( boost::json::Value& jsv, const bool& v );
00030 void pack( boost::json::Value& jsv, const float& v );
00031 void pack( boost::json::Value& jsv, const double& v );
00032 void pack( boost::json::Value& jsv, const uint8_t& v );
00033 void pack( boost::json::Value& jsv, const uint16_t& v );
00034 void pack( boost::json::Value& jsv, const uint32_t& v );
00035 void pack( boost::json::Value& jsv, const uint64_t& v );
00036 void pack( boost::json::Value& jsv, const int8_t& v );
00037 void pack( boost::json::Value& jsv, const int16_t& v );
00038 void pack( boost::json::Value& jsv, const int32_t& v );
00039 void pack( boost::json::Value& jsv, const int64_t& v );
00040 void pack( boost::json::Value& jsv, const signed_int& v );
00041 void pack( boost::json::Value& jsv, const unsigned_int& v );
00042 void pack( boost::json::Value& jsv, const std::string& v );
00043 void pack( boost::json::Value& jsv, const char* v );
00044 void pack( boost::json::Value& jsv, const std::vector<char>& value );
00045 template<typename T>
00046 void pack( boost::json::Value& jsv, const boost::optional<T>& v );
00047 template<typename T>
00048 void pack( boost::json::Value& jsv, const required<T>& v );
00049 template<typename T, typename Alloc, template<typename,typename> class Container>
00050 void pack( boost::json::Value& jsv, const Container<T,Alloc>& value );
00051 template<typename Key, typename Value>
00052 void pack( boost::json::Value& jsv, const std::map<Key,Value>& value );
00053 template<typename Key, typename Value>
00054 void pack( boost::json::Value& jsv, const std::pair<Key,Value>& value );
00055 template<typename Value>
00056 void pack( boost::json::Value& jsv, const std::map<std::string,Value>& value );
00057
00058
00059 template<typename T>
00060 void unpack( const boost::json::Value& jsv, const T& v );
00061 template<typename T>
00062 void unpack( const boost::json::Value& jsv, T& v );
00063 void unpack( const boost::json::Value& jsv, bool& v );
00064 void unpack( const boost::json::Value& jsv, float& v );
00065 void unpack( const boost::json::Value& jsv, double& v );
00066 void unpack( const boost::json::Value& jsv, uint8_t& v );
00067 void unpack( const boost::json::Value& jsv, uint16_t& v );
00068 void unpack( const boost::json::Value& jsv, uint32_t& v );
00069 void unpack( const boost::json::Value& jsv, uint64_t& v );
00070 void unpack( const boost::json::Value& jsv, int8_t& v );
00071 void unpack( const boost::json::Value& jsv, int16_t& v );
00072 void unpack( const boost::json::Value& jsv, int32_t& v );
00073 void unpack( const boost::json::Value& jsv, int64_t& v );
00074 void unpack( const boost::json::Value& jsv, signed_int& v );
00075 void unpack( const boost::json::Value& jsv, unsigned_int& v );
00076 void unpack( const boost::json::Value& jsv, std::string& v );
00077 void unpack( const boost::json::Value& jsv, std::vector<char>& value );
00078 template<typename T>
00079 void unpack( const boost::json::Value& jsv, boost::optional<T>& v );
00080 template<typename T>
00081 void unpack( const boost::json::Value& jsv, required<T>& v );
00082 template<typename T, typename Alloc, template<typename,typename> class Container>
00083 void unpack( const boost::json::Value& jsv, Container<T,Alloc>& value );
00084 template<typename Key, typename Value>
00085 void unpack( const boost::json::Value& jsv, std::map<Key,Value>& value );
00086 template<typename Key, typename Value>
00087 void unpack( const boost::json::Value& jsv, std::pair<Key,Value>& value );
00088 template<typename Value>
00089 void unpack( const boost::json::Value& jsv, std::map<std::string,Value>& value );
00090
00091 namespace detail {
00092 template<typename Class>
00093 struct pack_object_visitor {
00094 pack_object_visitor(const Class& _c, boost::json::Object& _val)
00095 :c(_c),obj(_val){}
00096
00101 template<typename T>
00102 void pack_helper( const T& v, const char* name )const {
00103 obj.push_back( boost::json::Pair(name,boost::json::Value()) );
00104 boost::rpc::json::pack( obj.back().value_, v );
00105 }
00106 template<typename T>
00107 void pack_helper( const boost::optional<T>& v, const char* name )const {
00108 if( !!v ) {
00109 obj.push_back( boost::json::Pair(name,boost::json::Value()) );
00110 boost::rpc::json::pack( obj.back().value_, *v );
00111 }
00112 }
00113 template<typename T>
00114 void operator()( T (Class::*p), const char* name )const {
00115 pack_helper( c.*p, name );
00116 }
00117
00118 private:
00119 const Class& c;
00120 boost::json::Object& obj;
00121 };
00122
00123 template<typename Class>
00124 struct unpack_object_visitor {
00125 unpack_object_visitor(Class& _c, const boost::json::Object& _val)
00126 :c(_c),obj(_val){}
00127
00128 template<typename T>
00129 void operator()( T (Class::*p), const char* name )const {
00130 std::string n(name);
00131 for( uint32_t i = 0; i < obj.size(); ++i ) {
00132 if( obj[i].name_ == n ) {
00133 boost::rpc::json::unpack( obj[i].value_, c.*p );
00134 return;
00135 }
00136 }
00137 }
00138 Class& c;
00139 const boost::json::Object& obj;
00140 };
00141
00142 struct pack_sequence {
00143 pack_sequence( boost::json::Array& _a ):a(_a){}
00144
00145 mutable boost::json::Array& a;
00146
00147 template<typename T>
00148 void operator() ( const T& v )const {
00149 a.push_back( boost::json::Value());
00150 boost::rpc::json::pack(a.back(),v);
00151 }
00152 };
00153 struct unpack_sequence {
00154 unpack_sequence( boost::json::Array::const_iterator& _a ):a(_a){}
00155
00156 mutable boost::json::Array::const_iterator& a;
00157
00158 template<typename T>
00159 void operator() ( T& v )const {
00160 if( a != boost::json::Array::const_iterator() ) {
00161 boost::rpc::json::unpack(*a,v);
00162 ++a;
00163 }
00164 }
00165 };
00166
00167 template<bool IsFusionSeq> struct if_fusion_seq {
00168 template<typename T>
00169 inline static void pack( boost::json::Value& jsv, const T& v ) {
00170 jsv = boost::json::Array();
00171 pack_sequence pack_vector(jsv.get_array());
00172 boost::fusion::for_each( v, pack_vector );
00173 }
00174 template<typename T>
00175 inline static void unpack( const boost::json::Value& jsv, T& v ) {
00176 boost::json::Array::const_iterator itr = jsv.get_array().begin();
00177 unpack_sequence unpack_vector(itr);
00178 boost::fusion::for_each( v, unpack_vector );
00179 }
00180 };
00181 template<> struct if_fusion_seq<false> {
00182 template<typename T>
00183 inline static void pack( boost::json::Value& jsv, const T& v ) {
00184 jsv = boost::json::Object();
00185 detail::pack_object_visitor<T> pov(v, jsv.get_obj());
00186 boost::reflect::reflector<T>::visit(pov);
00187 }
00188 template<typename T>
00189 inline static void unpack( const boost::json::Value& jsv, T& v ) {
00190 detail::unpack_object_visitor<T> pov(v, jsv.get_obj());
00191 boost::reflect::reflector<T>::visit(pov);
00192 }
00193 };
00194 }
00195
00196 inline void pack( boost::json::Value& jsv, const bool& v ) { jsv = boost::json::Value(v); }
00197 inline void pack( boost::json::Value& jsv, const float& v ) { jsv = boost::json::Value(v); }
00198 inline void pack( boost::json::Value& jsv, const double& v ) { jsv = boost::json::Value(v); }
00199 inline void pack( boost::json::Value& jsv, const uint8_t& v ) { jsv = boost::json::Value(v); }
00200 inline void pack( boost::json::Value& jsv, const uint16_t& v ) { jsv = boost::json::Value(v); }
00201 inline void pack( boost::json::Value& jsv, const uint32_t& v ) { jsv = boost::json::Value((uint64_t)v); }
00202 inline void pack( boost::json::Value& jsv, const uint64_t& v ) { jsv = boost::json::Value(v); }
00203 inline void pack( boost::json::Value& jsv, const int8_t& v ) { jsv = boost::json::Value(v); }
00204 inline void pack( boost::json::Value& jsv, const int16_t& v ) { jsv = boost::json::Value(v); }
00205 inline void pack( boost::json::Value& jsv, const int32_t& v ) { jsv = boost::json::Value(v); }
00206 inline void pack( boost::json::Value& jsv, const int64_t& v ) { jsv = boost::json::Value(v); }
00207 inline void pack( boost::json::Value& jsv, const signed_int& v ) { jsv = boost::json::Value((int64_t)v.value); }
00208 inline void pack( boost::json::Value& jsv, const unsigned_int& v ) { jsv = boost::json::Value((uint64_t)v.value); }
00209 inline void pack( boost::json::Value& jsv, const std::string& v ) { jsv = boost::json::Value(v); }
00210 inline void pack( boost::json::Value& jsv, const char* v ) { jsv = boost::json::Value(std::string(v)); }
00211
00212 inline void unpack( const boost::json::Value& jsv, bool& v ) { v = jsv.get_bool(); }
00213 inline void unpack( const boost::json::Value& jsv, float& v ) { v = (float)jsv.get_real(); }
00214 inline void unpack( const boost::json::Value& jsv, double& v ) { v = jsv.get_real(); }
00215 inline void unpack( const boost::json::Value& jsv, uint8_t& v ) { v = jsv.get_int(); }
00216 inline void unpack( const boost::json::Value& jsv, uint16_t& v ) { v = jsv.get_int(); }
00217 inline void unpack( const boost::json::Value& jsv, uint32_t& v ) { v = (uint32_t)jsv.get_int64();}
00218 inline void unpack( const boost::json::Value& jsv, uint64_t& v ) { v = jsv.get_uint64(); }
00219 inline void unpack( const boost::json::Value& jsv, int8_t& v ) { v = jsv.get_int(); }
00220 inline void unpack( const boost::json::Value& jsv, int16_t& v ) { v = jsv.get_int(); }
00221 inline void unpack( const boost::json::Value& jsv, int32_t& v ) { v = jsv.get_int(); }
00222 inline void unpack( const boost::json::Value& jsv, int64_t& v ) { v = jsv.get_int64(); }
00223 inline void unpack( const boost::json::Value& jsv, signed_int& v ) { v.value = (int32_t)jsv.get_int64(); }
00224 inline void unpack( const boost::json::Value& jsv, unsigned_int& v ) { v.value = (uint32_t)jsv.get_uint64(); }
00225 inline void unpack( const boost::json::Value& jsv, std::string& v ) { v = jsv.get_str(); }
00226
00227 template<typename T>
00228 inline void pack( boost::json::Value& jsv, const T& v ) {
00229 detail::if_fusion_seq< boost::fusion::traits::is_sequence<T>::value >::pack(jsv,v);
00230 }
00231
00232 template<typename T>
00233 inline void pack( boost::json::Value& jsv, const boost::optional<T>& v ) {
00234 boost::rpc::json::pack( jsv, *v );
00235 }
00236
00237 template<typename T>
00238 inline void pack( boost::json::Value& jsv, const required<T>& v ) {
00239 if( !v ) BOOST_THROW_EXCEPTION( boost::rpc::required_field_not_set() );
00240 boost::rpc::json::pack( jsv, *v );
00241 }
00242 template<typename T>
00243 inline void unpack( const boost::json::Value& jsv, required<T>& v ) {
00244 v = T();
00245 boost::rpc::json::unpack( jsv, *v );
00246 }
00247 template<typename T>
00248 inline void unpack( const boost::json::Value& jsv, optional<T>& v ) {
00249 v = T();
00250 boost::rpc::json::unpack( jsv, *v );
00251 }
00252
00253
00254 template<typename T, typename Alloc, template<typename,typename> class Container>
00255 inline void pack( boost::json::Value& jsv, const Container<T,Alloc>& value ) {
00256 jsv = boost::json::Array();
00257 boost::json::Array& a = jsv.get_array();
00258 a.resize(value.size());
00259 typename Container<T,Alloc>::const_iterator itr = value.begin();
00260 typename Container<T,Alloc>::const_iterator end = value.end();
00261 uint32_t i = 0;
00262 while( itr != end ) {
00263 boost::rpc::json::pack( a[i], *itr );
00264 ++itr;
00265 ++i;
00266 }
00267 }
00268
00269 template<typename T, typename Alloc, template<typename,typename> class Container>
00270 inline void unpack( const boost::json::Value& jsv, Container<T,Alloc>& value ) {
00271 const boost::json::Array& a = jsv.get_array();
00272 value.resize( a.size() );
00273 typename Container<T,Alloc>::iterator itr = value.begin();
00274 typename Container<T,Alloc>::iterator end = value.end();
00275 uint32_t i = 0;
00276 while( itr != end ) {
00277 boost::rpc::json::unpack( a[i], *itr );
00278 ++itr;
00279 ++i;
00280 }
00281 }
00282
00283
00284 template<typename Key, typename Value>
00285 inline void pack( boost::json::Value& jsv, const std::pair<Key,Value>& value ) {
00286 jsv = boost::json::Object();
00287 jsv.get_obj().push_back( boost::json::Pair( "first", boost::json::Value() ) );
00288 boost::rpc::json::pack(jsv.get_obj().back().value_, value.first );
00289 jsv.get_obj().push_back( boost::json::Pair( "second", boost::json::Value() ) );
00290 boost::rpc::json::pack(jsv.get_obj().back().value_, value.second );
00291 }
00292
00293 template<typename Key, typename Value>
00294 void unpack( const boost::json::Value& jsv, std::pair<Key,Value>& value ) {
00295 const boost::json::Object& obj = jsv.get_obj();
00296 if( obj.size() < 2 ) {
00297 BOOST_THROW_EXCEPTION( "Error unpacking pairs" );
00298 }
00299 if( obj[0].name_ == "first" )
00300 boost::rpc::json::unpack( obj[0].value_, value.first );
00301 if( obj[1].name_ == "second" )
00302 boost::rpc::json::unpack( obj[1].value_, value.second );
00303 }
00304
00305
00306
00307 template<typename Key, typename Value>
00308 void pack( boost::json::Value& jsv, const std::map<Key,Value>& value ) {
00309 jsv = boost::json::Array();
00310 boost::json::Array& a = jsv.get_array();
00311 a.resize(value.size());
00312 typename std::map<Key,Value>::const_iterator itr = value.begin();
00313 typename std::map<Key,Value>::const_iterator end = value.end();
00314 uint32_t i = 0;
00315 while( itr != end ) {
00316 boost::rpc::json::pack( a[i], *itr );
00317 ++itr;
00318 ++i;
00319 }
00320 }
00321
00322 template<typename Key, typename Value>
00323 inline void unpack( const boost::json::Value& jsv, std::map<Key,Value>& value ) {
00324 const boost::json::Array& a = jsv.get_array();
00325 value.clear();
00326 for( uint32_t i = 0; i < a.size(); ++i ) {
00327 std::pair<Key,Value> p;
00328 boost::rpc::json::unpack( a[i], p );
00329 value[p.first] = p.second;
00330 }
00331 }
00332
00333 inline void pack( boost::json::Value& jsv, const std::vector<char>& data ) {
00334 if( data.size() ) { pack( jsv, base64_encode((unsigned char*)&data.front(),data.size())); }
00335 }
00336 inline void unpack( const boost::json::Value& jsv, std::vector<char>& data ) {
00337 data.clear();
00338 std::string d = base64_decode(jsv.get_str());
00339 data.insert(data.begin(),d.begin(),d.end());
00340 }
00341
00342
00343
00344 template<typename Value>
00345 void pack( boost::json::Value& jsv, const std::map<std::string,Value>& value ) {
00346 jsv = boost::json::Object();
00347 boost::json::Object& o = jsv.get_obj();
00348 o.reserve(value.size());
00349 typename std::map<std::string,Value>::const_iterator itr = value.begin();
00350 typename std::map<std::string,Value>::const_iterator end = value.end();
00351 while( itr != end ) {
00352 o.push_back( boost::json::Pair(itr->first,boost::json::Value()));
00353 boost::rpc::json::pack( o.back().value_, itr->second );
00354 ++itr;
00355 }
00356 }
00357 template<typename Value>
00358 void unpack( const boost::json::Value& jsv, std::map<std::string,Value>& value ) {
00359 const boost::json::Object& o = jsv.get_obj();
00360 value.clear();
00361 for( uint32_t i = 0; i < o.size(); ++i ) {
00362 boost::rpc::json::unpack( o[i].value_, value[o[i].name_] );
00363 }
00364 }
00365 template<typename T>
00366 inline void unpack( const boost::json::Value& jsv, T& v ) {
00367 detail::if_fusion_seq< boost::fusion::traits::is_sequence<T>::value >::unpack(jsv,v);
00368 }
00369
00370 template<typename T>
00371 std::ostream& to_json( std::ostream& os, const T& v, uint32_t options = boost::json::remove_trailing_zeros ) {
00372 boost::json::Value jsv;
00373 pack( jsv, v );
00374 boost::json::write( jsv, os, options );
00375 return os;
00376 }
00377 template<typename T>
00378 std::ostream& to_jsonf( std::ostream& os, const T& v,
00379 uint32_t options = boost::json::pretty_print | boost::json::remove_trailing_zeros ) {
00380 return to_json(os,v,options);
00381 }
00382 template<typename T>
00383 std::string to_json( const T& v, uint32_t options=0 ) {
00384 std::ostringstream ss;
00385 to_json( ss, v, options );
00386 return ss.str();
00387 }
00388
00389 template<typename T>
00390 void from_json( const std::string& j, T& val ) {
00391 boost::json::Value v;
00392 boost::json::read( j, v );
00393 unpack( v, val );
00394 }
00395
00396 template<typename T>
00397 std::string to_jsonf( const T& v, uint32_t options=boost::json::pretty_print ) {
00398 return to_json(v,options);
00399 }
00400
00401 } } }
00402
00403 #endif // BOOST_RPC_JSON_HPP