CppCMS

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 {
83 is_undefined,
84 is_null,
85 is_boolean,
86 is_number,
87 is_string,
88 is_object,
89 is_array
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 }
529 value()
530 {
531 }
532
536
537 ~value()
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:
572 booster::copy_ptr<_data> d;
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
cppcms::json::traits::get
static T get(value const &v)
cppcms::json::value
This class is central representation of json objects.
Definition: json.h:140
cppcms::json::json_type
json_type
Definition: json.h:82
cppcms::json::compact
Print JSON values in most compact format.
Definition: json.h:94
cppcms::json::value::value
value(value const &other)
Definition: json.h:514
cppcms::json::value::type
json_type type(std::string const &path) const
Definition: json.h:322
cppcms::json::undefined
Special object that is convertible to undefined json value.
Definition: json.h:37
cppcms::json::is_boolean
boolean value
Definition: json.h:85
cppcms::json::is_string
string value
Definition: json.h:87
cppcms::json::value::type
json_type type() const
cppcms::json::object
std::map< string_key, value > object
The json::object - std::map of json::value&#39;s.
Definition: json.h:51
cppcms::json::value::array
json::array const & array() const
booster::copy_ptr< _data >
cppcms
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
cppcms::json::null
Special object that is convertible to null json value.
Definition: json.h:33
cppcms::json::value::get_value
T get_value() const
Definition: json.h:234
cppcms::json::value::set_value
void set_value(T const &v)
Definition: json.h:243
cppcms::json::value::value
value(T const &v)
Definition: json.h:312
cppcms::json::is_object
object value
Definition: json.h:88
cppcms::json::value::number
double const & number() const
cppcms::json::value::operator=
value const & operator=(value const &other)
Definition: json.h:521
cppcms::json::bad_value_cast
The error that is thrown in case of bad conversion of json::value to ordinary value.
Definition: json.h:104
cppcms::json::to_json
std::string CPPCMS_API to_json(std::string const &utf)
cppcms::json::value::swap
void swap(value &other)
Definition: json.h:544
cppcms::json::value::is_undefined
bool is_undefined() const
cppcms::json::operator<<
std::ostream CPPCMS_API & operator<<(std::ostream &out, value const &v)
cppcms::json::operator>>
std::istream CPPCMS_API & operator>>(std::istream &in, value &v)
cppcms::json::is_null
null value
Definition: json.h:84
booster::locale::as::number
std::ios_base & number(std::ios_base &ios)
Definition: formatting.h:292
cppcms::json::traits::set
static void set(value &v, T const &in)
booster::bad_cast
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
cppcms::json::value::type
json_type type(char const *path) const
Definition: json.h:331
cppcms::json::traits
The type traits schema for converting json values to/from orinary objects i.e. serialization from JSO...
Definition: json.h:60
cppcms::json::is_number
numeric value
Definition: json.h:86
cppcms::json::value::object
json::object const & object() const
cppcms::json::value::~value
~value()
Definition: json.h:537
cppcms::json::array
std::vector< value > array
The json::array - std::vector of json::value&#39;s.
Definition: json.h:47
cppcms::json::is_undefined
Undefined value.
Definition: json.h:83
cppcms::json::is_array
array value
Definition: json.h:89
cppcms::json::readable
Print JSON values in human readable format (with identention)
Definition: json.h:95
cppcms::json::value::value
value()
Definition: json.h:529