Bytemaster's Boost Libraries
|
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, typename C, T(C::*p)> 00114 inline void operator()( 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, typename C, T C::* p> 00129 inline void operator()( 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 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 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 } // namesapce detail 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 // support for pair! 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 // support for pair! 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 // support arbitrary key/value containers as an array of pairs 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 // pack map<string,T> as a JSON Object 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 } } } // namespace boost::rpc::json 00402 00403 #endif // BOOST_RPC_JSON_HPP