Classdesc 3.44
json_unpack_base.h
1/*
2 @copyright Russell Standish 2000-2013
3 @author Russell Standish
4 This file is part of Classdesc
5
6 Open source licensed under the MIT license. See LICENSE for details.
7*/
8
9#ifndef CLASSDESC_JSON_PACK_BASE_H
10#define CLASSDESC_JSON_PACK_BASE_H
11#include "classdesc.h"
12#define JSON5_PARSER_MVALUE_ENABLED
13#define BOOST_BIND_GLOBAL_PLACEHOLDERS
14#include <json5_parser_value.h>
15#include <json5_parser_reader_template.h>
16#include <json5_parser_writer_template.h>
17#include <stdio.h>
18#include <stdarg.h>
19#include <vector>
20#include <map>
21#include <cmath>
22
23#if defined(__cplusplus) && __cplusplus<201103L
24#include <math.h>
25namespace std
26{
27 using ::nan;
28}
29#endif
30
31namespace classdesc
32{
33
34 class json_pack_error : public exception
35 {
36 static const int maxchars=200; /* I hope this will always be large enough */
37 char errstring[maxchars];
38 public:
39 json_pack_error(const char *fmt,...)
40 {
41 va_list args;
42 va_start(args, fmt);
43 vsnprintf(errstring,maxchars,fmt,args);
44 va_end(args);
45 }
46 virtual ~json_pack_error() throw() {}
47 virtual const char* what() const throw() {return errstring;}
48 };
49
51 {
52 json_object_not_found(const string& name):
53 json_pack_error("json object %s not found", name.c_str()) {}
54 };
55
56 typedef std::map<json5_parser::Value_type,RESTProcessType::Type> RESTProcessTypeJSONMap_t;
57 const inline RESTProcessTypeJSONMap_t& RESTProcessTypeJSONMap()
58 {
59 static RESTProcessTypeJSONMap_t jsonMap;
60 if (jsonMap.empty())
61 {
62 jsonMap[json5_parser::obj_type]=RESTProcessType::object;
63 jsonMap[json5_parser::array_type]=RESTProcessType::array;
64 jsonMap[json5_parser::str_type]=RESTProcessType::string;
65 jsonMap[json5_parser::bool_type]=RESTProcessType::boolean;
66 jsonMap[json5_parser::int_type]=RESTProcessType::int_number;
67 jsonMap[json5_parser::real_type]=RESTProcessType::float_number;
68 jsonMap[json5_parser::null_type]=RESTProcessType::null;
69 }
70 return jsonMap;
71 };
72
74 inline RESTProcessType::Type Json5ParserTypeToRESTProcessType(json5_parser::Value_type type)
75 {
76 RESTProcessTypeJSONMap_t::const_iterator r=RESTProcessTypeJSONMap().find(type);
77 if (r!=RESTProcessTypeJSONMap().end()) return r->second;
78 return RESTProcessType::null;
79 }
80
82 inline json5_parser::Value_type RESTProcessTypeToJson5ParserType(RESTProcessType::Type type)
83 {
84 typedef std::map<RESTProcessType::Type,json5_parser::Value_type> Map;
85 static Map jsonMap;
86 if (jsonMap.empty())
87 {
88 const RESTProcessTypeJSONMap_t& m=RESTProcessTypeJSONMap();
89 for (RESTProcessTypeJSONMap_t::const_iterator i=m.begin(); i!=m.end(); ++i)
90 jsonMap.insert(std::make_pair(i->second,i->first));
91 }
92 Map::const_iterator r=jsonMap.find(type);
93 if (r!=jsonMap.end()) return r->second;
94 return json5_parser::null_type;
95 };
96
97 // these are classes, not typedefs to avoid adding properties to mValue
98 class json_pack_t: public json5_parser::mValue
99 {
100 public:
101 bool throw_on_error;
102 bool throw_on_not_found;
103
104 typedef json5_parser::mArray Array;
105 json_pack_t(): throw_on_error(false), throw_on_not_found(false) {}
106
107 template <class T>
108 explicit json_pack_t(const T& x,
109 typename enable_if<is_base_of<json5_parser::mValue,T>, dummy<0> >::T* d=0 ):
110 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
111
112 template <class T>
113 explicit json_pack_t(const T& x,
114 typename enable_if<is_base_of<json5_parser::mArray,T>, dummy<0> >::T* d=0 ):
115 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
116
117 template <class T>
118 explicit json_pack_t(const T& x,
119 typename enable_if<is_base_of<json5_parser::mObject,T>, dummy<0> >::T* d=0 ):
120 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
121
122 template <class T>
123 explicit json_pack_t(const T& x, typename enable_if<
124 And<
125 And<
126 Not<is_base_of<json5_parser::mValue,T> >,
127 Not<is_base_of<json5_parser::mArray,T> >
128 >,
129 Not<is_base_of<json5_parser::mObject,T> >
130 >, dummy<1> >::T* d=0);
131
132 explicit json_pack_t(bool x):
133 json5_parser::mValue(x),
134 throw_on_error(false), throw_on_not_found(false) {}
135 explicit json_pack_t(double x):
136 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
137 explicit json_pack_t(const char* x):
138 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
139 explicit json_pack_t(const string& x):
140 json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
141// explicit json_pack_t(const Array& x):
142// json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
143// explicit json_pack_t(const json5_parser::mValue& x):
144// json5_parser::mValue(x), throw_on_error(false), throw_on_not_found(false) {}
145#if defined(__cplusplus) && __cplusplus>=201103L
146 template <class T>
147 explicit json_pack_t(const std::initializer_list<T>& x): json5_parser::mValue(json5_parser::mArray())
148 {
149 auto& arr=get_array();
150 for (auto& i: x) arr.emplace_back(i);
151 }
152#endif
153
154 const Array& array() const {return get_array();}
155 RESTProcessType::Type type() const {
156 return Json5ParserTypeToRESTProcessType(json5_parser::mValue::type());
157 }
158
160 void objectify() {if (type()!=RESTProcessType::object) *this=json_pack_t(json5_parser::mObject());}
161
162 };
163
164 inline bool read(const std::string& s, json_pack_t& value)
165 {
166 return json5_parser::read_string(s, static_cast<json5_parser::mValue&>(value));
167 }
168
169 inline bool read(std::istream& is, json_pack_t& value)
170 {
171 return json5_parser::read_stream(is, static_cast<json5_parser::mValue&>(value));
172 }
173
174 inline void write(const json_pack_t& value, std::ostream& os, unsigned options=0)
175 {
176 json5_parser::write_stream(static_cast<const json5_parser::mValue&>(value), os, options );
177 }
178
179 inline std::string write(const json_pack_t& value, unsigned options=0)
180 {
181 return json5_parser::write_string(static_cast<const json5_parser::mValue&>(value), options );
182 }
183
184 inline void write_formatted(const json_pack_t& value, std::ostream& os)
185 {
186 write_stream( static_cast<const json5_parser::mValue&>(value), os, json5_parser::pretty_print );
187 }
188
189 inline std::string write_formatted(const json_pack_t& value)
190 {
191 return write_string( static_cast<const json5_parser::mValue&>(value), json5_parser::pretty_print );
192 }
193
194 typedef json_pack_t json_unpack_t;
195
197 template <class T> void json_pack(json_pack_t& o, const string& d, T& a);
198
199 template <class T> void json_pack(json_pack_t& o, const string& d, const T& a)
200 {json_pack(o,d,const_cast<T&>(a));}
201
202 template <class T> void json_unpack(json_unpack_t& o, const string& d, T& a);
203
204 template <class T> json_pack_t& operator<<(json_pack_t& j, const T& a)
205 {json_pack(j,"",a); return j;}
206
207 template <class T> const json_unpack_t& operator>>(const json_unpack_t& j, T& a)
208 {json_unpack(const_cast<json_unpack_t&>(j),"",a); return j;}
209
210 inline const json_unpack_t& operator>>(const json_unpack_t& j, const char*& a)
211 {throw json_pack_error("cannot unpack to char*, please use string instead");}
212
213 template <class T>
214 json_pack_t::json_pack_t(const T& x, typename enable_if<
215 And<
216 And<
217 Not<is_base_of<json5_parser::mValue,T> >,
218 Not<is_base_of<json5_parser::mArray,T> >
219 >,
220 Not<is_base_of<json5_parser::mObject,T> >
221 >, dummy<1> >::T*):
222 json5_parser::mValue(json5_parser::mObject()),
223 throw_on_error(false), throw_on_not_found(false)
224 {(*this)<<x;}
225
227 inline json5_parser::mValue&
228 json_find(json5_parser::mValue& x, std::string name)
229 {
230 if (name.size()==0) return x;
231 if (name[0]=='.') name.erase(0,1); //remove leading '.'
232 std::string::size_type p=name.find('.');
233 if (x.type()==json5_parser::obj_type)
234 {
235 json5_parser::mObject& xo=x.get_obj();
236 json5_parser::mObject::iterator i=xo.find(name.substr(0,p));
237 if (i==xo.end())
238 throw json_object_not_found(name.substr(0,p));
239 else if (p==std::string::npos)
240 return i->second;
241 else
242 return json_find(i->second,name.substr(p,std::string::npos));
243 }
244 else
245 throw json_pack_error("%s is not a json object",name.c_str());
246 }
247
248 //json5_parser::mValue does not provide constructors for everything. Oh well..
249 template <class T> json5_parser::mValue valueof(T a)
250 {return json5_parser::mValue(a);}
251 template <class T> T getValue(const json5_parser::mValue& x)
252 {return x.get_value<T>();}
253
254 inline json5_parser::mValue valueof(unsigned char a)
255 {return json5_parser::mValue(int(a));}
256 template <> inline unsigned char getValue(const json5_parser::mValue& x)
257 {return x.get_value<int>();}
258
259 inline json5_parser::mValue valueof(signed char a)
260 {return json5_parser::mValue(int(a));}
261 template <> inline signed char getValue(const json5_parser::mValue& x)
262 {return x.get_value<int>();}
263
264 inline json5_parser::mValue valueof(char a)
265 {return json5_parser::mValue(string()+a);}
266 template <> inline char getValue(const json5_parser::mValue& x)
267 {return x.get_value<string>()[0];}
268
269 inline json5_parser::mValue valueof(unsigned short a)
270 {return json5_parser::mValue(int(a));}
271 template <> inline unsigned short getValue(const json5_parser::mValue& x)
272 {return x.get_value<int>();}
273
274 inline json5_parser::mValue valueof(signed short a)
275 {return json5_parser::mValue(int(a));}
276 template <> inline signed short getValue(const json5_parser::mValue& x)
277 {return x.get_value<int>();}
278
279 inline json5_parser::mValue valueof(unsigned int a)
280 {return json5_parser::mValue(boost::uint64_t(a));}
281 template <> inline unsigned getValue(const json5_parser::mValue& x)
282 {return x.get_value<boost::uint64_t>();}
283
284 inline json5_parser::mValue valueof(unsigned long a)
285 {return json5_parser::mValue(boost::uint64_t(a));}
286 template <> inline unsigned long getValue(const json5_parser::mValue& x)
287 {return x.get_value<boost::uint64_t>();}
288
289 inline json5_parser::mValue valueof(long a)
290 {return json5_parser::mValue(boost::int64_t(a));}
291 template <> inline long getValue(const json5_parser::mValue& x)
292 {return x.get_value<boost::int64_t>();}
293
294#ifdef HAVE_LONGLONG
295 inline json5_parser::mValue valueof(unsigned long long a)
296 {return json5_parser::mValue(boost::uint64_t(a));}
297 template <> inline unsigned long long getValue(const json5_parser::mValue& x)
298 {return x.get_value<boost::uint64_t>();}
299
300 inline json5_parser::mValue valueof(long long a)
301 {return json5_parser::mValue(boost::int64_t(a));}
302 template <> inline long long getValue(const json5_parser::mValue& x)
303 {return x.get_value<boost::int64_t>();}
304#endif
305
306 inline json5_parser::mValue valueof(float a)
307 {return json5_parser::mValue(double(a));}
308
309 template <> inline float getValue(const json5_parser::mValue& x)
310 {
311 // treat nulls as nans - JSON.stringify of special values returns "null"
312 if (x.type()==json5_parser::null_type) return std::nan("");
313 return x.get_value<double>();
314 }
315
316 template <> inline double getValue(const json5_parser::mValue& x)
317 {
318 // treat nulls as nans - JSON.stringify of special values returns "null"
319 if (x.type()==json5_parser::null_type) return std::nan("");
320 return x.get_value<double>();
321 }
322
323 // basic types
324 template <class T> typename
326 json_packp(json_unpack_t& o, const string& d, const T& a, dummy<0> dum=0)
327 {
328 using namespace json5_parser;
329 if (d=="")
330 {
331 json_pack_t tmp(valueof(a));
332 o=tmp;
333 }
334 else
335 {
336 o.objectify();
337 try
338 {
339 json5_parser::mValue& parent=json_find(o,head(d));
340 if (parent.type()==obj_type)
341 parent.get_obj()[tail(d)]=valueof(a);
342 else
343 throw json_pack_error("cannot add to a basic type");
344 }
345 catch (const json_object_not_found&)
346 {
347 // only throw if this flag is set
348 if (o.throw_on_not_found) throw;
349 }
350 catch (const json_pack_error&)
351 {
352 // only throw if this flag is set
353 if (o.throw_on_error) throw;
354 }
355 }
356 }
357
358 // basic types
359 template <class T> typename
361 json_unpackp(json_unpack_t& o, string d, T& a, dummy<0> dum=0)
362 {
363 try
364 {
365 a=getValue<T>(json_find(o,d));
366 }
367 catch (const json_pack_error&)
368 {
369 // only throw if this flag is set
370 if (o.throw_on_error) throw;
371 }
372 }
373
374 template <class T> void json_pack_isarray
375 (json5_parser::mValue& jval, const T& val, std::vector<size_t> dims)
376 {
377 if (dims.empty())
378 {
379 json_pack_t j;
380 json_pack(j,"",val);
381 jval=j;
382 }
383 else
384 {
385 size_t s=dims.back();
386 jval=json5_parser::mArray(s);
387 dims.pop_back();
388 size_t stride=1;
389 for (size_t i=0; i<dims.size(); ++i) stride*=dims[i];
390 for (size_t i=0; i<s; ++i)
391 json_pack_isarray(jval.get_array()[i],(&val)[i*stride], dims);
392 }
393 }
394
395 // array handling
396 template <class T>
397 void json_pack(json_pack_t& o, const string& d, is_array ia, const T& a,
398 int ndims,size_t ncopies,...)
399 {
400 va_list ap;
401 va_start(ap,ncopies);
402 std::vector<size_t> dims(ndims);
403 dims[ndims-1]=ncopies;
404 for (int i=ndims-2; i>=0; --i) dims[i]=va_arg(ap,size_t);
405 va_end(ap);
406 try
407 {
408 json5_parser::mValue& parent=json_find(o,head(d));
409 if (parent.type()!=json5_parser::obj_type)
410 throw json_pack_error("attempt to pack an array member into a non-object");
411 else
412 json_pack_isarray(parent.get_obj()[tail(d)],a,dims);
413 }
414 catch (json_pack_error&)
415 {
416 // only throw if this flag is set
417 if (o.throw_on_error) throw;
418 }
419 }
420
421 template <class T> void json_unpack_isarray
422 (const json5_parser::mValue& jval, T& val, std::vector<size_t> dims)
423 {
424 if (dims.empty())
425 {
426 json_unpack_t j(jval);
427 json_unpack(j,"",val);
428 }
429 else
430 {
431 size_t s=dims.back();
432 dims.pop_back();
433 size_t stride=1;
434 for (size_t i=0; i<dims.size(); ++i) stride*=dims[i];
435 for (size_t i=0; i<s; ++i)
436 json_unpack_isarray(jval.get_array()[i],(&val)[i*stride], dims);
437 }
438 }
439
440 template <class T>
441 void json_unpack(json_unpack_t& o, const string& d, is_array ia, T& a,
442 int ndims,size_t ncopies,...)
443 {
444 va_list ap;
445 va_start(ap,ncopies);
446 std::vector<size_t> dims(ndims);
447 dims[ndims-1]=ncopies;
448 for (int i=ndims-2; i>=0; --i) dims[i]=va_arg(ap,size_t);
449 va_end(ap);
450 try
451 {
452 const json5_parser::mValue& v=json_find(o,d);
453 if (v.type()!=json5_parser::array_type)
454 throw json_pack_error
455 ("attempt to unpack an array member from a non-object");
456 else
457 json_unpack_isarray(v,a,dims);
458 }
459 catch (json_pack_error&)
460 {
461 // only throw if this flag is set
462 if (o.throw_on_error) throw;
463 }
464
465 }
466
467
471
472 template <class T> void json_pack(json_pack_t& x, const string& d,
473 Enum_handle<T> arg)
474 {
475 string tmp(static_cast<string>(arg));
476 json_pack(x,d,tmp);
477 }
478
479 //Enum_handles have reference semantics
480 template <class T> void json_unpack(json_unpack_t& x, const string& d,
481 Enum_handle<T> arg)
482 {
483 std::string tmp;
484 json_unpack(x,d,tmp);
485 // remove extraneous white space
486 int (*isspace)(int)=std::isspace;
487 std::string::iterator end=std::remove_if(tmp.begin(),tmp.end(),isspace);
488 arg=tmp.substr(0,end-tmp.begin());
489 }
490
492 template <class T> typename
494 json_unpackp(json_unpack_t& o, const string& d, T& a, dummy<1> dum=0)
495 {
496 try
497 {
498 const json5_parser::mValue& val=json_find(o,d);
499 if (val.type()!=json5_parser::array_type)
500 throw json_pack_error("%s is not an array",d.c_str());
501 else
502 {
503 const json5_parser::mArray& arr=val.get_array();
504 resize(a, arr.size());
505 size_t i=0;
506 for (typename T::iterator j=a.begin(); i<arr.size() && j!=a.end(); ++i, ++j)
507 {
508 json_unpack_t jp(arr[i]);
509 json_unpack(jp,"",*j);
510 }
511 }
512 }
513 catch (json_pack_error&)
514 {
515 if (o.throw_on_error) throw;
516 }
517 }
518
519 template <class T1, class T2>
520 void json_pack(json_pack_t& o, const string& d, std::pair<T1,T2>& a)
521 {
522 o.objectify();
523 json_pack(o,d+".first",a.first);
524 json_pack(o,d+".second",a.second);
525 }
526
527 template <class T1, class T2>
528 void json_unpackp(json_unpack_t& o, const string& d, std::pair<T1,T2>& a)
529 {
530 json_unpack(o,d+".first",a.first);
531 json_unpack(o,d+".second",a.second);
532 }
533
534 template <class T> typename
536 json_packp(json_pack_t& o, const string& d, const T& a, dummy<1> dum=0)
537 {
538 o.objectify();
539 try
540 {
541 json5_parser::mValue& parent=json_find(o,head(d));
542 if (parent.type()!=json5_parser::obj_type)
543 throw json_pack_error("attempt to pack an array member into a non-object");
544 else
545 {
546 json5_parser::mValue* v;
547 if (d.empty())
548 v=&parent;
549 else
550 v=&parent.get_obj()[tail(d)];
551
552 json5_parser::mArray& arr=
553 (*v=json5_parser::mArray(a.size())).get_array();
554 typename T::const_iterator i=a.begin();
555 for (size_t k=0; i!=a.end(); ++i, ++k)
556 {
557 json_pack_t j;
558 json_pack(j,"",*i);
559 arr[k]=j;
560 }
561 }
562 }
563 catch (json_pack_error&)
564 {
565 if (o.throw_on_error) throw;
566 }
567 }
568
569 template <class T> typename
571 json_unpackp(json_unpack_t& o, const string& d, T& a, dummy<2> dum=0)
572 {
573 try
574 {
575 const json5_parser::mValue& val=json_find(o,d);
576 if (val.type()!=json5_parser::array_type)
577 throw json_pack_error("%s is not an array",d.c_str());
578 else
579 {
580 const json5_parser::mArray& arr=val.get_array();
581 a.clear();
582 for (size_t i=0; i<arr.size(); ++i)
583 {
584 // certain linters fail to recognise that this variable is initialised in the json_unpack call
585#if defined(__cplusplus) && __cplusplus>=201103L
586 typename NonConstKeyValueType<typename T::value_type>::T v{};
587#else
588 typename NonConstKeyValueType<typename T::value_type>::T v;
589#endif
590 json_unpack_t j(arr[i]);
591 json_unpack(j,"",v);
592 a.insert(v);
593 }
594 }
595 }
596 catch (json_pack_error&)
597 {
598 if (o.throw_on_error) throw;
599 }
600 }
601
602 /*
603 const static support
604 */
605 template <class T>
606 void//typename enable_if<Not<is_pointer<T> >,void>::T
607 json_pack(json_pack_t& targ, const string& desc, is_const_static, T)
608 {}
609
610 template <class T>
611 void//typename enable_if<Not<is_pointer<T> >,void>::T
612 json_unpack(json_unpack_t& targ, const string& desc, is_const_static, T)
613 {}
614
615 template <class T>
616 typename enable_if<is_object<T>, void>::T
617 json_unpack(json_unpack_t& targ, const string& desc, T*) {}
618
619 template <class T>
620 void json_unpack(json_unpack_t& targ, const string& desc, const T& arg) {}
621
622 template <class T>
623 void json_pack(json_pack_t& targ, const string& desc, Exclude<T>& arg) {}
624
625 template <class T>
626 void json_unpack(json_unpack_t& targ, const string& desc, Exclude<T>& arg) {}
627
628 template <class T, class U>
629 void json_pack(json_pack_t& targ, const string& desc, T&, is_constructor, U&) {}
630
631 template <class T, class U>
632 void json_unpack(json_unpack_t& targ, const string& desc, T&, is_constructor, U&) {}
633
635 template <class T> string json(const T& x)
636 {
637 json_pack_t j;
638 json_pack(j,"",x);
639 return write(j);
640 }
641 template <class T> void json(T& x, const string& s)
642 {
643 json_pack_t j;
644 read(s, j);
645 json_unpack(j,"",x);
646 }
647
648 template <class T>
649 void json_pack_onbase(json_pack_t& x,const string& d,T& a)
650 {json_pack(x,d+basename<T>(),a);}
651
652 template <class T>
653 void json_unpack_onbase(json_unpack_t& x,const string& d,T& a)
654 {json_unpack(x,d+basename<T>(),a);}
655
656}
657
658inline std::ostream& operator<<(std::ostream& o, const json5_parser::mValue& x)
659{
660 json5_parser::write_stream(x,o);
661 return o;
662}
663
664namespace classdesc_access
665{
666 template <class T, class Enable=void> struct access_json_pack;
667 template <class T, class Enable=void> struct access_json_unpack;
668}
669
670#include "use_mbr_pointers.h"
671CLASSDESC_USE_OLDSTYLE_MEMBER_OBJECTS(json_pack)
672CLASSDESC_USE_OLDSTYLE_MEMBER_OBJECTS(json_unpack)
673CLASSDESC_FUNCTION_NOP(json_pack)
674CLASSDESC_FUNCTION_NOP(json_unpack)
675
676
677using classdesc::json_pack_onbase;
678using classdesc::json_unpack_onbase;
679
681using classdesc::json_unpack;
682#endif
Definition classdesc.h:868
Definition classdesc.h:920
Definition classdesc.h:923
Definition classdesc.h:926
Definition json_pack_base.h:35
Definition json_pack_base.h:99
void objectify()
convert this to an object type (if not already)
Definition json_unpack_base.h:160
bool throw_on_not_found
enable exceptions if element not present in JSON stream
Definition json_pack_base.h:102
bool throw_on_error
enable exceptions on error conditions
Definition json_pack_base.h:101
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
json5_parser::mValue & json_find(json5_parser::mValue &x, std::string name)
find an object named by name within the json object x
Definition json_pack_base.h:228
string basename()
returns a valid identifier to append to the descriptor of a base class
Definition classdesc.h:1127
json5_parser::Value_type RESTProcessTypeToJson5ParserType(RESTProcessType::Type type)
convert a RESTProcessType::Type to a json5_parser::Value_type
Definition json_pack_base.h:82
void json_pack(json_pack_t &o, const string &d, T &a)
forward declare generic json operations
Definition json_pack_epilogue.h:61
RESTProcessType::Type Json5ParserTypeToRESTProcessType(json5_parser::Value_type type)
convert a json5_parser::Value_type to a RESTProcessType::Type
Definition json_pack_base.h:74
string json(const T &x)
produce json string equivalent of object x
Definition json_pack_base.h:635
STL namespace.
Definition classdesc.h:420
Definition classdesc.h:1012
Definition classdesc.h:405
Definition classdesc.h:299
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
base class for exceptions thrown by classdesc
Definition classdesc.h:546
determines if T is a standard associative container
Definition classdesc.h:321
determines if this is a string
Definition classdesc.h:313
Definition json_pack_base.h:51
Definition json_pack_epilogue.h:92
Definition json_pack_epilogue.h:104