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 
29 
30  class value;
31 
35  struct null {};
39  struct undefined {};
40 
41  inline bool operator==(undefined const &/*l*/,undefined const &/*r*/) {return true;}
42  inline bool operator!=(undefined const &/*l*/,undefined const &/*r*/) {return false;}
43  inline bool operator==(null const &/*l*/,null const &/*r*/) {return true;}
44  inline bool operator!=(null const &/*l*/,null const &/*r*/) {return false;}
45 
49  typedef std::vector<value> array;
53  typedef std::map<string_key,value> object;
54 
55  #ifdef CPPCMS_DOXYGEN_DOCS
56 
61  template<typename T>
62  struct traits {
66  static T get(value const &v);
70  static void set(value &v,T const &in);
71  };
72 
73  #else
74 
75  template<typename T>
76  struct traits;
77 
78  #endif
79 
80 
84  typedef enum {
92  } json_type;
93 
94 
95  enum {
96  compact = 0,
97  readable = 1
98  };
99 
106  class CPPCMS_API bad_value_cast : public booster::bad_cast {
107  public:
108  bad_value_cast();
109  bad_value_cast(std::string const &s);
110  bad_value_cast(std::string const &s,json_type actual);
111  bad_value_cast(std::string const &s,json_type expected, json_type actual);
112 
113  virtual ~bad_value_cast() throw();
114  virtual const char* what() const throw();
115  private:
116  std::string msg_;
117  };
118 
119  class value;
120 
124  std::istream CPPCMS_API &operator>>(std::istream &in,value &v);
125 
129  std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v);
130 
134  std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type);
135 
142  class CPPCMS_API value {
143  public:
144 
148  json_type type() const;
149 
153  bool is_undefined() const;
157  bool is_null() const;
158 
162  bool const &boolean() const;
166  double const &number() const;
170  std::string const &str() const;
174  json::object const &object() const;
178  json::array const &array() const;
179 
183  bool &boolean();
187  double &number();
191  std::string &str();
195  json::object &object();
199  json::array &array();
200 
204  void undefined();
208  void null();
209 
213  void boolean(bool);
217  void number(double );
221  void str(std::string const &);
225  void object(json::object const &);
229  void array(json::array const &);
230 
231 
235  template<typename T>
236  T get_value() const
237  {
238  return traits<T>::get(*this);
239  }
240 
244  template<typename T>
245  void set_value(T const &v)
246  {
247  traits<T>::set(*this,v);
248  }
249 
257  value const &find(std::string const &path) const;
265  value const &find(char const *path) const;
266 
274  value const &at(std::string const &path) const;
282  value const &at(char const *path) const;
290  value &at(std::string const &path);
298  value &at(char const *path);
299 
303  void at(std::string const &path,value const &v);
307  void at(char const *path,value const &v);
308 
309 
313  template<typename T>
314  value(T const &v)
315  {
316  set_value(v);
317  }
318 
324  json_type type(std::string const &path) const
325  {
326  return find(path).type();
327  }
333  json_type type(char const *path) const
334  {
335  return find(path).type();
336  }
337 
341  template<typename T>
342  void set(std::string const &path,T const &v)
343  {
344  at(path,value(v));
345  }
349  template<typename T>
350  void set(char const *path,T const &v)
351  {
352  at(path,value(v));
353  }
354 
359  std::string get(std::string const &path,char const *def) const
360  {
361  value const &v=find(path);
362  if(v.is_undefined())
363  return def;
364  try {
365  return v.get_value<std::string>();
366  }
367  catch(std::bad_cast const &e) {
368  return def;
369  }
370  }
375  std::string get(char const *path,char const *def) const
376  {
377  value const &v=find(path);
378  if(v.is_undefined())
379  return def;
380  try {
381  return v.get_value<std::string>();
382  }
383  catch(std::bad_cast const &e) {
384  return def;
385  }
386  }
387 
392  template<typename T>
393  T get(std::string const &path) const
394  {
395  return at(path).get_value<T>();
396  }
401  template<typename T>
402  T get(char const *path) const
403  {
404  return at(path).get_value<T>();
405  }
406 
411  template<typename T>
412  T get(char const *path,T const &def) const
413  {
414  value const &v=find(path);
415  if(v.is_undefined())
416  return def;
417  try {
418  return v.get_value<T>();
419  }
420  catch(std::bad_cast const &e) {
421  return def;
422  }
423  }
428  template<typename T>
429  T get(std::string const &path,T const &def) const
430  {
431  value const &v=find(path);
432  if(v.is_undefined())
433  return def;
434  try {
435  return v.get_value<T>();
436  }
437  catch(std::bad_cast const &e) {
438  return def;
439  }
440  }
441 
449  value &operator[](std::string const &name);
450 
457  value const &operator[](std::string const &name) const;
458 
463  value &operator[](size_t n);
468  value const &operator[](size_t n) const;
469 
473  std::string save(int how=compact) const;
477  void save(std::ostream &out,int how=compact) const;
488  bool load(std::istream &in,bool full,int *line_number=0);
489 
493  bool operator==(value const &other) const;
497  bool operator!=(value const &other) const;
498 
502  value(value const &other) :
503  d(other.d)
504  {
505  }
509  value const &operator=(value const &other)
510  {
511  d=other.d;
512  return *this;
513  }
518  {
519  }
520 
524 
526  {
527  }
528 
532  void swap(value &other)
533  {
534  d.swap(other.d);
535  }
536 
537  private:
538 
539  void write(std::ostream &out,int tabs) const;
540  void write_value(std::ostream &out,int tabs) const;
541 
542  struct _data;
543  struct CPPCMS_API copyable {
544 
545  _data *operator->() { return &*d; }
546  _data &operator*() { return *d; }
547  _data const *operator->() const { return &*d; }
548  _data const &operator*() const { return *d; }
549 
550  copyable();
551  copyable(copyable const &r);
552  copyable const &operator=(copyable const &r);
553  ~copyable();
554 
555  void swap(copyable &other)
556  {
557  d.swap(other.d);
558  }
559  private:
561  } d;
562 
563  friend struct copyable;
564  };
565 
566 
567 
569 
570  template<typename T1,typename T2>
571  struct traits<std::pair<T1,T2> > {
572  static std::pair<T1,T2> get(value const &v)
573  {
574  if(v.object().size()!=2)
575  throw bad_value_cast("Object with two members expected");
576  std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second"));
577  return pair;
578  }
579  static void set(value &v,std::pair<T1,T2> const &in)
580  {
581  v=json::object();
582  v.set_value("first",in.first);
583  v.set_value("second",in.second);
584  }
585  };
586 
587  template<typename T>
588  struct traits<std::vector<T> > {
589  static std::vector<T> get(value const &v)
590  {
591  std::vector<T> result;
592  json::array const &a=v.array();
593  result.resize(a.size());
594  for(unsigned i=0;i<a.size();i++)
595  result[i]=a[i].get_value<T>();
596  return result;
597  }
598  static void set(value &v,std::vector<T> const &in)
599  {
600  v=json::array();
601  json::array &a=v.array();
602  a.resize(in.size());
603  for(unsigned i=0;i<in.size();i++)
604  a[i].set_value(in[i]);
605  }
606  };
607 
608 
609  #define CPPCMS_JSON_SPECIALIZE(type,method) \
610  template<> \
611  struct traits<type> { \
612  static type get(value const &v) \
613  { \
614  return v.method(); \
615  } \
616  static void set(value &v,type const &in)\
617  { \
618  v.method(in); \
619  } \
620  };
621 
622  CPPCMS_JSON_SPECIALIZE(bool,boolean);
623  CPPCMS_JSON_SPECIALIZE(double,number);
624  CPPCMS_JSON_SPECIALIZE(std::string,str);
625  CPPCMS_JSON_SPECIALIZE(json::object,object);
626  CPPCMS_JSON_SPECIALIZE(json::array,array);
627 
628  #undef CPPCMS_JSON_SPECIALIZE
629 
630  #define CPPCMS_JSON_SPECIALIZE_INT(type) \
631  template<> \
632  struct traits<type> { \
633  static type get(value const &v) \
634  { \
635  type res=static_cast<type>(v.number()); \
636  if(res!=v.number()) \
637  throw bad_value_cast(); \
638  return res; \
639  } \
640  static void set(value &v,type const &in) \
641  { \
642  if(std::numeric_limits<type>::digits > \
643  std::numeric_limits<double>::digits \
644  && static_cast<double>(in)!=in) \
645  { \
646  throw bad_value_cast(); \
647  } \
648  v.number(static_cast<double>(in)); \
649  } \
650  };
651 
652  CPPCMS_JSON_SPECIALIZE_INT(char)
653  CPPCMS_JSON_SPECIALIZE_INT(unsigned char)
654  CPPCMS_JSON_SPECIALIZE_INT(signed char)
655  CPPCMS_JSON_SPECIALIZE_INT(wchar_t)
656  CPPCMS_JSON_SPECIALIZE_INT(short)
657  CPPCMS_JSON_SPECIALIZE_INT(unsigned short)
658  CPPCMS_JSON_SPECIALIZE_INT(int)
659  CPPCMS_JSON_SPECIALIZE_INT(unsigned int)
660  CPPCMS_JSON_SPECIALIZE_INT(long)
661  CPPCMS_JSON_SPECIALIZE_INT(unsigned long)
662  CPPCMS_JSON_SPECIALIZE_INT(long long)
663  CPPCMS_JSON_SPECIALIZE_INT(unsigned long long)
664 
665  #undef CPPCMS_JSON_SPECIALIZE_INT
666 
667  template<>
668  struct traits<float> {
669  static float get(value const &v)
670  {
671  double r=v.number();
672  if( r < std::numeric_limits<float>::min()
673  || std::numeric_limits<float>::max() < r )
674  {
675  throw bad_value_cast();
676  }
677  return static_cast<float>(r);
678  }
679  static void set(value &v,float const &in)
680  {
681  v.number(in);
682  }
683  };
684 
685  template<>
686  struct traits<long double> {
687  static long double get(value const &v)
688  {
689  return v.number();
690  }
691  static void set(value &v,long double const &in)
692  {
693  if( in < std::numeric_limits<double>::min()
694  || std::numeric_limits<double>::max() < in )
695  {
696  throw bad_value_cast();
697  }
698  v.number(static_cast<double>(in));
699  }
700  };
701 
702  template<>
703  struct traits<json::null> {
704  static void set(value &v,json::null const &/*in*/)
705  {
706  v.null();
707  }
708  };
709 
710  template<int n>
711  struct traits<char[n]> {
712  typedef char vtype[n];
713  static void set(value &v,vtype const &in)
714  {
715  v.str(in);
716  }
717  };
718  template<int n>
719  struct traits<char const [n]> {
720  typedef char const vtype[n];
721  static void set(value &v,vtype const &in)
722  {
723  v.str(in);
724  }
725  };
726 
727 
728  template<>
729  struct traits<char const *> {
730  static void set(value &v,char const * const &in)
731  {
732  v.str(in);
733  }
734  };
735 
737 
738 
739 } // json
740 } // cppcms
741 
742 #endif
static T get(value const &v)
This class is central representation of json objects.
Definition: json.h:142
json_type
Definition: json.h:84
Print JSON values in most compact format.
Definition: json.h:96
void set(char const *path, T const &v)
Definition: json.h:350
value(value const &other)
Definition: json.h:502
json_type type(std::string const &path) const
Definition: json.h:324
Special object that is convertible to undefined json value.
Definition: json.h:39
boolean value
Definition: json.h:87
string value
Definition: json.h:89
std::map< string_key, value > object
The json::object - std::map of json::value's.
Definition: json.h:53
Special object that is convertible to null json value.
Definition: json.h:35
T get_value() const
Definition: json.h:236
void set_value(T const &v)
Definition: json.h:245
date_time_period operator*(period::period_type f, T v)
Definition: date_time.h:335
value(T const &v)
Definition: json.h:314
object value
Definition: json.h:90
value const & operator=(value const &other)
Definition: json.h:509
The error that is thrown in case of bad conversion of json::value to ordinary value.
Definition: json.h:106
void swap(value &other)
Definition: json.h:532
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:86
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:333
The type traits schema for converting json values to/from orinary objects i.e. serialization from JSO...
Definition: json.h:62
numeric value
Definition: json.h:88
~value()
Definition: json.h:525
std::vector< value > array
The json::array - std::vector of json::value's.
Definition: json.h:49
Undefined value.
Definition: json.h:85
array value
Definition: json.h:91
Print JSON values in human readable format (with identention)
Definition: json.h:97
void set(std::string const &path, T const &v)
Definition: json.h:342
value()
Definition: json.h:517