CppCMS
json.h
1 //
3 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
4 //
5 // See accompanying file COPYING.TXT file for licensing details.
6 //
8 #ifndef CPPCMS_JSON_H
9 #define CPPCMS_JSON_H
10 
11 #include <cppcms/defs.h>
12 #include <cppcms/string_key.h>
13 #include <booster/copy_ptr.h>
14 #include <booster/backtrace.h>
15 #include <vector>
16 #include <map>
17 #include <string>
18 #include <iostream>
19 #include <limits>
20 
21 namespace cppcms {
25 namespace json {
26 
27 
28  class value;
29 
33  struct null {};
37  struct undefined {};
38 
39  inline bool operator==(undefined const &/*l*/,undefined const &/*r*/) {return true;}
40  inline bool operator!=(undefined const &/*l*/,undefined const &/*r*/) {return false;}
41  inline bool operator==(null const &/*l*/,null const &/*r*/) {return true;}
42  inline bool operator!=(null const &/*l*/,null const &/*r*/) {return false;}
43 
47  typedef std::vector<value> array;
51  typedef std::map<string_key,value> object;
52 
53  #ifdef CPPCMS_DOXYGEN_DOCS
54 
59  template<typename T>
60  struct traits {
64  static T get(value const &v);
68  static void set(value &v,T const &in);
69  };
70 
71  #else
72 
73  template<typename T>
74  struct traits;
75 
76  #endif
77 
78 
82  typedef enum {
90  } json_type;
91 
92 
93  enum {
94  compact = 0,
95  readable = 1
96  };
97 
104  class CPPCMS_API bad_value_cast : public booster::bad_cast {
105  public:
106  bad_value_cast();
107  bad_value_cast(std::string const &s);
108  bad_value_cast(std::string const &s,json_type actual);
109  bad_value_cast(std::string const &s,json_type expected, json_type actual);
110 
111  virtual ~bad_value_cast() throw();
112  virtual const char* what() const throw();
113  private:
114  std::string msg_;
115  };
116 
117  class value;
118 
122  std::istream CPPCMS_API &operator>>(std::istream &in,value &v);
123 
127  std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v);
128 
132  std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type);
133 
140  class CPPCMS_API value {
141  public:
142 
146  json_type type() const;
147 
151  bool is_undefined() const;
155  bool is_null() const;
156 
160  bool const &boolean() const;
164  double const &number() const;
168  std::string const &str() const;
172  json::object const &object() const;
176  json::array const &array() const;
177 
181  bool &boolean();
185  double &number();
189  std::string &str();
193  json::object &object();
197  json::array &array();
198 
202  void undefined();
206  void null();
207 
211  void boolean(bool);
215  void number(double );
219  void str(std::string const &);
223  void object(json::object const &);
227  void array(json::array const &);
228 
229 
233  template<typename T>
234  T get_value() const
235  {
236  return traits<T>::get(*this);
237  }
238 
242  template<typename T>
243  void set_value(T const &v)
244  {
245  traits<T>::set(*this,v);
246  }
247 
255  value const &find(std::string const &path) const;
263  value const &find(char const *path) const;
264 
272  value const &at(std::string const &path) const;
280  value const &at(char const *path) const;
288  value &at(std::string const &path);
296  value &at(char const *path);
297 
301  void at(std::string const &path,value const &v);
305  void at(char const *path,value const &v);
306 
307 
311  template<typename T>
312  value(T const &v)
313  {
314  set_value(v);
315  }
316 
322  json_type type(std::string const &path) const
323  {
324  return find(path).type();
325  }
331  json_type type(char const *path) const
332  {
333  return find(path).type();
334  }
335 
339  template<typename T>
340  void set(std::string const &path,T const &v)
341  {
342  at(path,value(v));
343  }
347  template<typename T>
348  void set(char const *path,T const &v)
349  {
350  at(path,value(v));
351  }
352 
357  std::string get(std::string const &path,char const *def) const
358  {
359  value const &v=find(path);
360  if(v.is_undefined())
361  return def;
362  try {
363  return v.get_value<std::string>();
364  }
365  catch(std::bad_cast const &e) {
366  return def;
367  }
368  }
373  std::string get(char const *path,char const *def) const
374  {
375  value const &v=find(path);
376  if(v.is_undefined())
377  return def;
378  try {
379  return v.get_value<std::string>();
380  }
381  catch(std::bad_cast const &e) {
382  return def;
383  }
384  }
385 
390  template<typename T>
391  T get(std::string const &path) const
392  {
393  return at(path).get_value<T>();
394  }
399  template<typename T>
400  T get(char const *path) const
401  {
402  return at(path).get_value<T>();
403  }
404 
409  template<typename T>
410  T get(char const *path,T const &def) const
411  {
412  value const &v=find(path);
413  if(v.is_undefined())
414  return def;
415  try {
416  return v.get_value<T>();
417  }
418  catch(std::bad_cast const &e) {
419  return def;
420  }
421  }
426  template<typename T>
427  T get(std::string const &path,T const &def) const
428  {
429  value const &v=find(path);
430  if(v.is_undefined())
431  return def;
432  try {
433  return v.get_value<T>();
434  }
435  catch(std::bad_cast const &e) {
436  return def;
437  }
438  }
439 
447  value &operator[](std::string const &name);
448 
455  value const &operator[](std::string const &name) const;
456 
461  value &operator[](size_t n);
466  value const &operator[](size_t n) const;
467 
471  std::string save(int how=compact) const;
475  void save(std::ostream &out,int how=compact) const;
486  bool load(std::istream &in,bool full,int *line_number=0);
487 
500  bool load(char const *&begin,char const *end,bool full,int *line_number=0);
501 
505  bool operator==(value const &other) const;
509  bool operator!=(value const &other) const;
510 
514  value(value const &other) :
515  d(other.d)
516  {
517  }
521  value const &operator=(value const &other)
522  {
523  d=other.d;
524  return *this;
525  }
530  {
531  }
532 
536 
538  {
539  }
540 
544  void swap(value &other)
545  {
546  d.swap(other.d);
547  }
548 
549  private:
550 
551  void write(std::ostream &out,int tabs) const;
552  void write_value(std::ostream &out,int tabs) const;
553 
554  struct _data;
555  struct CPPCMS_API copyable {
556 
557  _data *operator->() { return &*d; }
558  _data &operator*() { return *d; }
559  _data const *operator->() const { return &*d; }
560  _data const &operator*() const { return *d; }
561 
562  copyable();
563  copyable(copyable const &r);
564  copyable const &operator=(copyable const &r);
565  ~copyable();
566 
567  void swap(copyable &other)
568  {
569  d.swap(other.d);
570  }
571  private:
573  } d;
574 
575  friend struct copyable;
576  };
577 
578 
584  std::string CPPCMS_API to_json(std::string const &utf);
590  std::string CPPCMS_API to_json(char const *begin,char const *end);
596  void CPPCMS_API to_json(char const *begin,char const *end,std::ostream &out);
597  //
602  void CPPCMS_API to_json(std::string const &str,std::ostream &out);
603 
604 
606 
607  template<typename T1,typename T2>
608  struct traits<std::pair<T1,T2> > {
609  static std::pair<T1,T2> get(value const &v)
610  {
611  if(v.object().size()!=2)
612  throw bad_value_cast("Object with two members expected");
613  std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second"));
614  return pair;
615  }
616  static void set(value &v,std::pair<T1,T2> const &in)
617  {
618  v=json::object();
619  v.set_value("first",in.first);
620  v.set_value("second",in.second);
621  }
622  };
623 
624  template<typename T>
625  struct traits<std::vector<T> > {
626  static std::vector<T> get(value const &v)
627  {
628  std::vector<T> result;
629  json::array const &a=v.array();
630  result.resize(a.size());
631  for(unsigned i=0;i<a.size();i++)
632  result[i]=a[i].get_value<T>();
633  return result;
634  }
635  static void set(value &v,std::vector<T> const &in)
636  {
637  v=json::array();
638  json::array &a=v.array();
639  a.resize(in.size());
640  for(unsigned i=0;i<in.size();i++)
641  a[i].set_value(in[i]);
642  }
643  };
644 
645 
646  #define CPPCMS_JSON_SPECIALIZE(type,method) \
647  template<> \
648  struct traits<type> { \
649  static type get(value const &v) \
650  { \
651  return v.method(); \
652  } \
653  static void set(value &v,type const &in)\
654  { \
655  v.method(in); \
656  } \
657  };
658 
659  CPPCMS_JSON_SPECIALIZE(bool,boolean);
660  CPPCMS_JSON_SPECIALIZE(double,number);
661  CPPCMS_JSON_SPECIALIZE(std::string,str);
662  CPPCMS_JSON_SPECIALIZE(json::object,object);
663  CPPCMS_JSON_SPECIALIZE(json::array,array);
664 
665  #undef CPPCMS_JSON_SPECIALIZE
666 
667  #define CPPCMS_JSON_SPECIALIZE_INT(type) \
668  template<> \
669  struct traits<type> { \
670  static type get(value const &v) \
671  { \
672  type res=static_cast<type>(v.number()); \
673  if(res!=v.number()) \
674  throw bad_value_cast(); \
675  return res; \
676  } \
677  static void set(value &v,type const &in) \
678  { \
679  if(std::numeric_limits<type>::digits > \
680  std::numeric_limits<double>::digits \
681  && static_cast<double>(in)!=in) \
682  { \
683  throw bad_value_cast(); \
684  } \
685  v.number(static_cast<double>(in)); \
686  } \
687  };
688 
689  CPPCMS_JSON_SPECIALIZE_INT(char)
690  CPPCMS_JSON_SPECIALIZE_INT(unsigned char)
691  CPPCMS_JSON_SPECIALIZE_INT(signed char)
692  CPPCMS_JSON_SPECIALIZE_INT(wchar_t)
693  CPPCMS_JSON_SPECIALIZE_INT(short)
694  CPPCMS_JSON_SPECIALIZE_INT(unsigned short)
695  CPPCMS_JSON_SPECIALIZE_INT(int)
696  CPPCMS_JSON_SPECIALIZE_INT(unsigned int)
697  CPPCMS_JSON_SPECIALIZE_INT(long)
698  CPPCMS_JSON_SPECIALIZE_INT(unsigned long)
699  CPPCMS_JSON_SPECIALIZE_INT(long long)
700  CPPCMS_JSON_SPECIALIZE_INT(unsigned long long)
701 
702  #undef CPPCMS_JSON_SPECIALIZE_INT
703 
704  template<>
705  struct traits<float> {
706  static float get(value const &v)
707  {
708  double r=v.number();
709  if( r < (-std::numeric_limits<float>::max()) // actually should be C++11 lowest, but it should be under IEEE float lowest()=-max()
710  || std::numeric_limits<float>::max() < r )
711  {
712  throw bad_value_cast();
713  }
714  return static_cast<float>(r);
715  }
716  static void set(value &v,float const &in)
717  {
718  v.number(in);
719  }
720  };
721 
722  template<>
723  struct traits<long double> {
724  static long double get(value const &v)
725  {
726  return v.number();
727  }
728  static void set(value &v,long double const &in)
729  {
730  if( in < -std::numeric_limits<double>::max() // should actually be std::numeric_limits<float>::lowest() but it is ==-max()
731  || std::numeric_limits<double>::max() < in )
732  {
733  throw bad_value_cast();
734  }
735  v.number(static_cast<double>(in));
736  }
737  };
738 
739  template<>
740  struct traits<json::null> {
741  static void set(value &v,json::null const &/*in*/)
742  {
743  v.null();
744  }
745  };
746 
747  template<int n>
748  struct traits<char[n]> {
749  typedef char vtype[n];
750  static void set(value &v,vtype const &in)
751  {
752  v.str(in);
753  }
754  };
755  template<int n>
756  struct traits<char const [n]> {
757  typedef char const vtype[n];
758  static void set(value &v,vtype const &in)
759  {
760  v.str(in);
761  }
762  };
763 
764 
765  template<>
766  struct traits<char const *> {
767  static void set(value &v,char const * const &in)
768  {
769  v.str(in);
770  }
771  };
772 
774 
775 
776 } // json
777 } // cppcms
778 
779 #endif
static T get(value const &v)
This class is central representation of json objects.
Definition: json.h:140
json_type
Definition: json.h:82
Print JSON values in most compact format.
Definition: json.h:94
value(value const &other)
Definition: json.h:514
json_type type(std::string const &path) const
Definition: json.h:322
Special object that is convertible to undefined json value.
Definition: json.h:37
boolean value
Definition: json.h:85
string value
Definition: json.h:87
json_type type() const
std::map< string_key, value > object
The json::object - std::map of json::value&#39;s.
Definition: json.h:51
json::array const & array() const
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
Special object that is convertible to null json value.
Definition: json.h:33
T get_value() const
Definition: json.h:234
void set_value(T const &v)
Definition: json.h:243
value(T const &v)
Definition: json.h:312
object value
Definition: json.h:88
double const & number() const
value const & operator=(value const &other)
Definition: json.h:521
The error that is thrown in case of bad conversion of json::value to ordinary value.
Definition: json.h:104
std::string CPPCMS_API to_json(std::string const &utf)
void swap(value &other)
Definition: json.h:544
bool is_undefined() const
std::ostream CPPCMS_API & operator<<(std::ostream &out, value const &v)
std::istream CPPCMS_API & operator>>(std::istream &in, value &v)
null value
Definition: json.h:84
std::ios_base & number(std::ios_base &ios)
Definition: formatting.h:292
static void set(value &v, T const &in)
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
json_type type(char const *path) const
Definition: json.h:331
The type traits schema for converting json values to/from orinary objects i.e. serialization from JSO...
Definition: json.h:60
numeric value
Definition: json.h:86
json::object const & object() const
~value()
Definition: json.h:537
std::vector< value > array
The json::array - std::vector of json::value&#39;s.
Definition: json.h:47
Undefined value.
Definition: json.h:83
array value
Definition: json.h:89
Print JSON values in human readable format (with identention)
Definition: json.h:95
value()
Definition: json.h:529